aiobungie
A Pythonic async/await wrapper for interacting with the Bungie API.
Base client.
Example
import aiobungie
client = aiobungie.Client('YOUR_API_KEY')
# Search for Destiny2 users.
async def main() -> None:
async with client.rest:
users = await client.search_users('Crit')
# Iterate over the users and take the first 5 results.
for user in users.take(5):
print(f'{user.name} ({user.code})')
# Iterate through the users memberships.
for membership in user.memberships:
print(membership.type, membership.id)
client.run(main()) # or asyncio.run(main())
Single RESTClient instance.
The difference between base client and the REST clients:
- No Hight-Level concepts.
- All returned data are pure JSON objects from the API.
- No object creation.
Example
import aiobungie
async def main() -> None:
# Using `async with` context manager to close the session properly.
async with aiobungie.RESTClient("TOKEN") as rest:
payload = await rest.fetch_player('Fate怒', 4275)
for membership in payload:
print(membership['membershipId'], membership['iconPath'])
import asyncio
asyncio.run(main())
REST client pool.
A REST client pool allows you to acquire multiple RESTClient instances that shares the same connection.
Example
import aiobungie
import asyncio
pool = aiobungie.RESTPool("token")
async def func1() -> None:
async with pool.acquire() as instance:
tokens = await instance.fetch_oauth2_tokens('code')
pool.metadata['tokens'] = tokens
# Other instance may access the tokens from pool since its shared.
async def func2() -> None:
async with pool.acquire() as instance:
tokens = pool.metadata['tokens']
tokens = await instance.refresh_access_token(tokens.refresh_token)
async def main() -> None:
await asyncio.gather(func1(), func2())
asyncio.run(main())
Should you use the base client or the REST client? This returns to you. For an example if you're building a website.
You can use python as a REST API in the backend with the RESTClient since all returned object are JSON objects. Which gives you the freedom to deserialize it and implement your own logic in the front-end.
Or of you're building a Discord bot for an example or something simple. The base client is the way to go.
1# MIT License 2# 3# Copyright (c) 2020 - Present nxtlo 4# 5# Permission is hereby granted, free of charge, to any person obtaining a copy 6# of this software and associated documentation files (the "Software"), to deal 7# in the Software without restriction, including without limitation the rights 8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9# copies of the Software, and to permit persons to whom the Software is 10# furnished to do so, subject to the following conditions: 11# 12# The above copyright notice and this permission notice shall be included in all 13# copies or substantial portions of the Software. 14# 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21# SOFTWARE. 22 23"""A Pythonic `async`/`await` wrapper for interacting with the Bungie API. 24 25Base client. 26 27Example 28------- 29```py 30import aiobungie 31 32client = aiobungie.Client('YOUR_API_KEY') 33 34# Search for Destiny2 users. 35async def main() -> None: 36 async with client.rest: 37 users = await client.search_users('Crit') 38 39 # Iterate over the users and take the first 5 results. 40 for user in users.take(5): 41 print(f'{user.name} ({user.code})') 42 43 # Iterate through the users memberships. 44 for membership in user.memberships: 45 print(membership.type, membership.id) 46 47client.run(main()) # or asyncio.run(main()) 48``` 49 50Single RESTClient instance. 51 52The difference between base client and the REST clients: 53 54* No Hight-Level concepts. 55* All returned data are pure JSON objects from the API. 56* No object creation. 57 58Example 59------- 60```py 61import aiobungie 62 63async def main() -> None: 64 # Using `async with` context manager to close the session properly. 65 async with aiobungie.RESTClient("TOKEN") as rest: 66 payload = await rest.fetch_player('Fate怒', 4275) 67 68 for membership in payload: 69 print(membership['membershipId'], membership['iconPath']) 70 71import asyncio 72asyncio.run(main()) 73``` 74 75REST client pool. 76 77A REST client pool allows you to acquire multiple `RESTClient` instances that shares the same connection. 78 79Example 80------- 81```py 82import aiobungie 83import asyncio 84 85pool = aiobungie.RESTPool("token") 86 87async def func1() -> None: 88 async with pool.acquire() as instance: 89 tokens = await instance.fetch_oauth2_tokens('code') 90 pool.metadata['tokens'] = tokens 91 92# Other instance may access the tokens from pool since its shared. 93 94async def func2() -> None: 95 async with pool.acquire() as instance: 96 tokens = pool.metadata['tokens'] 97 tokens = await instance.refresh_access_token(tokens.refresh_token) 98 99async def main() -> None: 100 await asyncio.gather(func1(), func2()) 101 102asyncio.run(main()) 103``` 104 105Should you use the base client or the REST client? 106This returns to you. For an example if you're building a website. 107 108You can use python as a REST API in the backend with the RESTClient since all returned object are JSON objects. 109Which gives you the freedom to deserialize it and implement your own logic in the front-end. 110 111Or of you're building a Discord bot for an example or something simple. The base client is the way to go. 112""" 113 114 115from __future__ import annotations 116 117from aiobungie import builders 118from aiobungie import crates 119from aiobungie import interfaces 120from aiobungie import traits 121from aiobungie import typedefs 122from aiobungie import url 123from aiobungie.client import Client 124from aiobungie.error import * 125from aiobungie.internal import iterators 126from aiobungie.internal.assets import Image 127from aiobungie.internal.enums import * 128from aiobungie.internal.factory import Factory 129from aiobungie.internal.iterators import * 130from aiobungie.rest import * 131from aiobungie.undefined import UNDEFINED 132from aiobungie.undefined import UndefinedOr 133from aiobungie.undefined import UndefinedType 134 135from .metadata import __about__ 136from .metadata import __author__ 137from .metadata import __docs__ 138from .metadata import __email__ 139from .metadata import __license__ 140from .metadata import __url__ 141from .metadata import __version__ 142 143# Alias for crate for backwards compatibility. 144crate = crates 145 146# Activity enums 147from .crates.activity import Difficulty 148 149# Components enums 150from .crates.components import ComponentFields 151from .crates.components import ComponentPrivacy 152 153# Entity enums 154from .crates.entity import GatingScope 155from .crates.entity import ObjectiveUIStyle 156from .crates.entity import ValueUIStyle 157 158# Fireteam enums. 159from .crates.fireteams import FireteamActivity 160from .crates.fireteams import FireteamDate 161from .crates.fireteams import FireteamLanguage 162from .crates.fireteams import FireteamPlatform 163 164# Records enums 165from .crates.records import RecordState 166 167__all__ = [mod for mod in dir() if not mod.startswith("_")] # type: ignore
74@attrs.define(auto_exc=True) 75class AiobungieError(RuntimeError): 76 """Base class that all other exceptions inherit from."""
Base class that all other exceptions inherit from.
Inherited Members
- builtins.BaseException
- with_traceback
- args
645@typing.final 646class AmmoType(int, Enum): 647 """AN enum for Detyiny 2 ammo types.""" 648 649 NONE = 0 650 PRIMARY = 1 651 SPECIAL = 2 652 HEAVY = 3
AN enum for Detyiny 2 ammo types.
164@attrs.define(auto_exc=True) 165class BadRequest(HTTPError): 166 """An exception raised when requesting a resource with the provided data is wrong.""" 167 168 url: typing.Optional[typedefs.StrOrURL] 169 """The URL/endpoint caused this error.""" 170 171 body: typing.Any 172 """The response body.""" 173 174 headers: multidict.CIMultiDictProxy[str] 175 """The response headers.""" 176 177 http_status: http.HTTPStatus = attrs.field( 178 default=http.HTTPStatus.BAD_REQUEST, init=False 179 )
An exception raised when requesting a resource with the provided data is wrong.
2def __init__(self, message, url, body, headers): 3 self.message = message 4 self.url = url 5 self.body = body 6 self.headers = headers 7 self.http_status = attr_dict['http_status'].default 8 BaseException.__init__(self, self.message,self.url,self.body,self.headers)
Method generated by attrs for class BadRequest.
700@typing.final 701class ClanMemberType(int, Enum): 702 """An enum for bungie clan member types.""" 703 704 NONE = 0 705 BEGINNER = 1 706 MEMBER = 2 707 ADMIN = 3 708 ACTING_FOUNDER = 4 709 FOUNDER = 5
An enum for bungie clan member types.
476@typing.final 477class Class(int, Enum): 478 """An Enum for Destiny character classes.""" 479 480 TITAN = 0 481 HUNTER = 1 482 WARLOCK = 2 483 UNKNOWN = 3
An Enum for Destiny character classes.
60class Client(traits.ClientApp): 61 """Standard Bungie API client application. 62 63 This client deserialize the REST JSON responses using `aiobungie.internal.factory.Factory` 64 and returns `aiobungie.crates` Python object implementations of the responses. 65 66 A `aiobungie.RESTClient` REST client can also be used alone for low-level concepts. 67 68 Example 69 ------- 70 ```py 71 import aiobungie 72 73 client = aiobungie.Client('...') 74 75 async def main(): 76 async with client.rest: 77 user = await client.fetch_current_user_memberships('...') 78 print(user) 79 ``` 80 81 Parameters 82 ----------- 83 token: `str` 84 Your Bungie's API key or Token from the developer's portal. 85 86 Other Parameters 87 ---------------- 88 max_retries : `int` 89 The max retries number to retry if the request hit a `5xx` status code. 90 client_secret : `str | None` 91 An optional application client secret, 92 This is only needed if you're fetching OAuth2 tokens with this client. 93 client_id : `int | None` 94 An optional application client id, 95 This is only needed if you're fetching OAuth2 tokens with this client. 96 """ 97 98 __slots__ = ("_rest", "_factory") 99 100 def __init__( 101 self, 102 token: str, 103 /, 104 *, 105 client_secret: typing.Optional[str] = None, 106 client_id: typing.Optional[int] = None, 107 max_retries: int = 4, 108 ) -> None: 109 self._rest = rest_.RESTClient( 110 token, 111 client_secret=client_secret, 112 client_id=client_id, 113 max_retries=max_retries, 114 ) 115 116 self._factory = factory_.Factory(self) 117 118 @property 119 def factory(self) -> factory_.Factory: 120 return self._factory 121 122 @property 123 def rest(self) -> interfaces.RESTInterface: 124 return self._rest 125 126 @property 127 def request(self) -> Client: 128 return self 129 130 @property 131 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: 132 return self._rest.metadata 133 134 def run( 135 self, future: collections.Coroutine[typing.Any, None, None], debug: bool = False 136 ) -> None: 137 loop: typing.Final[asyncio.AbstractEventLoop] = helpers.get_or_make_loop() 138 try: 139 if not loop.is_running(): 140 loop.set_debug(debug) 141 loop.run_until_complete(future) 142 143 except Exception as exc: 144 raise RuntimeError(f"Failed to run {future.__qualname__}") from exc 145 146 except KeyboardInterrupt: 147 _LOG.warn("Unexpected Keyboard interrupt. Exiting.") 148 return 149 150 # * User methods. 151 152 async def fetch_current_user_memberships(self, access_token: str, /) -> user.User: 153 """Fetch and return a user object of the bungie net user associated with account. 154 155 .. warning:: 156 This method requires OAuth2 scope and a Bearer access token. 157 158 Parameters 159 ---------- 160 access_token : `str` 161 A valid Bearer access token for the authorization. 162 163 Returns 164 ------- 165 `aiobungie.crates.user.User` 166 A user object includes the Destiny memberships and Bungie.net user. 167 """ 168 resp = await self.rest.fetch_current_user_memberships(access_token) 169 170 return self.factory.deserialize_user(resp) 171 172 async def fetch_bungie_user(self, id: int, /) -> user.BungieUser: 173 """Fetch a Bungie user by their BungieNet id. 174 175 .. note:: 176 This returns a Bungie user membership only. Take a look at `Client.fetch_membership_from_id` 177 for other memberships. 178 179 Parameters 180 ---------- 181 id: `int` 182 The user id. 183 184 Returns 185 ------- 186 `aiobungie.crates.user.BungieUser` 187 A Bungie user. 188 189 Raises 190 ------ 191 `aiobungie.error.NotFound` 192 The user was not found. 193 """ 194 payload = await self.rest.fetch_bungie_user(id) 195 196 return self.factory.deserialize_bungie_user(payload) 197 198 async def search_users( 199 self, name: str, / 200 ) -> iterators.Iterator[user.SearchableDestinyUser]: 201 """Search for players and return all players that matches the same name. 202 203 Parameters 204 ---------- 205 name : `buildins.str` 206 The user name. 207 208 Returns 209 ------- 210 `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]` 211 A sequence of destiny memberships. 212 """ 213 payload = await self.rest.search_users(name) 214 215 return iterators.Iterator( 216 [ 217 self.factory.deserialize_searched_user(user) 218 for user in payload["searchResults"] 219 ] 220 ) 221 222 async def fetch_user_themes(self) -> collections.Sequence[user.UserThemes]: 223 """Fetch all available user themes. 224 225 Returns 226 ------- 227 `collections.Sequence[aiobungie.crates.user.UserThemes]` 228 A sequence of user themes. 229 """ 230 data = await self.rest.fetch_user_themes() 231 232 return self.factory.deserialize_user_themes(data) 233 234 async def fetch_hard_types( 235 self, 236 credential: int, 237 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, 238 /, 239 ) -> user.HardLinkedMembership: 240 """Gets any hard linked membership given a credential. 241 Only works for credentials that are public just `aiobungie.CredentialType.STEAMID` right now. 242 Cross Save aware. 243 244 Parameters 245 ---------- 246 credential: `int` 247 A valid SteamID64 248 type: `aiobungie.CredentialType` 249 The credential type. This must not be changed 250 Since its only credential that works "currently" 251 252 Returns 253 ------- 254 `aiobungie.crates.user.HardLinkedMembership` 255 Information about the hard linked data. 256 """ 257 258 payload = await self.rest.fetch_hardlinked_credentials(credential, type) 259 260 return user.HardLinkedMembership( 261 id=int(payload["membershipId"]), 262 type=enums.MembershipType(payload["membershipType"]), 263 cross_save_type=enums.MembershipType(payload["CrossSaveOverriddenType"]), 264 ) 265 266 async def fetch_membership_from_id( 267 self, 268 id: int, 269 /, 270 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 271 ) -> user.User: 272 """Fetch Bungie user's memberships from their id. 273 274 Notes 275 ----- 276 * This returns both BungieNet membership and a sequence of the player's DestinyMemberships 277 Which includes Stadia, Xbox, Steam and PSN memberships if the player has them, 278 see `aiobungie.crates.user.DestinyMembership` for more details. 279 * If you only want the bungie user. Consider using `Client.fetch_user` method. 280 281 Parameters 282 ---------- 283 id : `int` 284 The user's id. 285 type : `aiobungie.MembershipType` 286 The user's membership type. 287 288 Returns 289 ------- 290 `aiobungie.crates.User` 291 A Bungie user with their membership types. 292 293 Raises 294 ------ 295 aiobungie.NotFound 296 The requested user was not found. 297 """ 298 payload = await self.rest.fetch_membership_from_id(id, type) 299 300 return self.factory.deserialize_user(payload) 301 302 async def fetch_user_credentials( 303 self, access_token: str, membership_id: int, / 304 ) -> collections.Sequence[user.UserCredentials]: 305 """Fetch an array of credential types attached to the requested account. 306 307 .. note:: 308 This method require OAuth2 Bearer access token. 309 310 Parameters 311 ---------- 312 access_token : `str` 313 The bearer access token associated with the bungie account. 314 membership_id : `int` 315 The id of the membership to return. 316 317 Returns 318 ------- 319 `collections.Sequence[aiobungie.crates.UserCredentials]` 320 A sequence of the attached user credentials. 321 322 Raises 323 ------ 324 `aiobungie.Unauthorized` 325 The access token was wrong or no access token passed. 326 """ 327 resp = await self.rest.fetch_user_credentials(access_token, membership_id) 328 329 return self.factory.deserialize_user_credentials(resp) 330 331 # * Destiny 2. 332 333 async def fetch_profile( 334 self, 335 member_id: int, 336 type: typedefs.IntAnd[enums.MembershipType], 337 components: list[enums.ComponentType], 338 auth: typing.Optional[str] = None, 339 ) -> components.Component: 340 """ 341 Fetch a bungie profile passing components to the request. 342 343 Parameters 344 ---------- 345 member_id: `int` 346 The member's id. 347 type: `aiobungie.MembershipType` 348 A valid membership type. 349 components : `list[aiobungie.ComponentType]` 350 List of profile components to collect and return. 351 352 Other Parameters 353 ---------------- 354 auth : `typing.Optional[str]` 355 A Bearer access_token to make the request with. 356 This is optional and limited to components that only requires an Authorization token. 357 358 Returns 359 -------- 360 `aiobungie.crates.Component` 361 A Destiny 2 player profile with its components. 362 Only passed components will be available if they exists. Otherwise they will be `None` 363 364 Raises 365 ------ 366 `aiobungie.MembershipTypeError` 367 The provided membership type was invalid. 368 """ 369 data = await self.rest.fetch_profile(member_id, type, components, auth) 370 return self.factory.deserialize_components(data) 371 372 async def fetch_linked_profiles( 373 self, 374 member_id: int, 375 member_type: typedefs.IntAnd[enums.MembershipType], 376 /, 377 *, 378 all: bool = False, 379 ) -> profile.LinkedProfile: 380 """Returns a summary information about all profiles linked to the requested member. 381 382 The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships. 383 384 .. note:: 385 It will only return linked accounts whose linkages you are allowed to view. 386 387 Parameters 388 ---------- 389 member_id : `int` 390 The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID. 391 member_type : `aiobungie.MembershipType` 392 The type for the membership whose linked Destiny account you want to return. 393 394 Other Parameters 395 ---------------- 396 all : `bool` 397 If provided and set to `True`, All memberships regardless 398 of whether they're obscured by overrides will be returned, 399 400 If provided and set to `False`, Only available memberships will be returned. 401 The default for this is `False`. 402 403 Returns 404 ------- 405 `aiobungie.crates.profile.LinkedProfile` 406 A linked profile object. 407 """ 408 resp = await self.rest.fetch_linked_profiles(member_id, member_type, all=all) 409 410 return self.factory.deserialize_linked_profiles(resp) 411 412 async def fetch_player( 413 self, 414 name: str, 415 code: int, 416 /, 417 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, 418 ) -> collections.Sequence[user.DestinyMembership]: 419 """Fetch a Destiny 2 player's memberships. 420 421 Parameters 422 ----------- 423 name: `str` 424 The unique Bungie player name. 425 code : `int` 426 The unique Bungie display name code. 427 type: `aiobungie.internal.enums.MembershipType` 428 The player's membership type, e,g. XBOX, STEAM, PSN 429 430 Returns 431 -------- 432 `collections.Sequence[aiobungie.crates.DestinyMembership]` 433 A sequence of the found Destiny 2 player memberships. 434 An empty sequence will be returned if no one found. 435 436 Raises 437 ------ 438 `aiobungie.MembershipTypeError` 439 The provided membership type was invalid. 440 """ 441 resp = await self.rest.fetch_player(name, code, type) 442 443 return self.factory.deserialize_destiny_memberships(resp) 444 445 async def fetch_character( 446 self, 447 member_id: int, 448 membership_type: typedefs.IntAnd[enums.MembershipType], 449 character_id: int, 450 components: list[enums.ComponentType], 451 auth: typing.Optional[str] = None, 452 ) -> components.CharacterComponent: 453 """Fetch a Destiny 2 character. 454 455 Parameters 456 ---------- 457 member_id: `int` 458 A valid bungie member id. 459 character_id: `int` 460 The Destiny character id to retrieve. 461 membership_type: `aiobungie.internal.enums.MembershipType` 462 The member's membership type. 463 components: `list[aiobungie.ComponentType]` 464 Multiple arguments of character components to collect and return. 465 466 Other Parameters 467 ---------------- 468 auth : `typing.Optional[str]` 469 A Bearer access_token to make the request with. 470 This is optional and limited to components that only requires an Authorization token. 471 472 Returns 473 ------- 474 `aiobungie.crates.CharacterComponent` 475 A Bungie character component. 476 477 `aiobungie.MembershipTypeError` 478 The provided membership type was invalid. 479 """ 480 resp = await self.rest.fetch_character( 481 member_id, membership_type, character_id, components, auth 482 ) 483 484 return self.factory.deserialize_character_component(resp) 485 486 async def fetch_unique_weapon_history( 487 self, 488 membership_id: int, 489 character_id: int, 490 membership_type: typedefs.IntAnd[enums.MembershipType], 491 ) -> collections.Sequence[activity.ExtendedWeaponValues]: 492 """Fetch details about unique weapon usage for a character. Includes all exotics. 493 494 Parameters 495 ---------- 496 membership_id : `int` 497 The Destiny user membership id. 498 character_id : `int` 499 The character id to retrieve. 500 membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 501 The Destiny user's membership type. 502 503 Returns 504 ------- 505 `collections.Sequence[aiobungie.crates.ExtendedWeaponValues]` 506 A sequence of the weapon's extended values. 507 """ 508 resp = await self._rest.fetch_unique_weapon_history( 509 membership_id, character_id, membership_type 510 ) 511 512 return [ 513 self._factory.deserialize_extended_weapon_values(weapon) 514 for weapon in resp["weapons"] 515 ] 516 517 # * Destiny 2 Activities. 518 519 async def fetch_activities( 520 self, 521 member_id: int, 522 character_id: int, 523 mode: typedefs.IntAnd[enums.GameMode], 524 *, 525 membership_type: typedefs.IntAnd[ 526 enums.MembershipType 527 ] = enums.MembershipType.ALL, 528 page: int = 0, 529 limit: int = 250, 530 ) -> iterators.Iterator[activity.Activity]: 531 """Fetch a Destiny 2 activity for the specified character id. 532 533 Parameters 534 ---------- 535 member_id: `int` 536 The user id that starts with `4611`. 537 character_id: `int` 538 The id of the character to retrieve the activities for. 539 mode: `aiobungie.typedefs.IntAnd[aiobungie.internal.enums.GameMode]` 540 This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc. 541 542 Other Parameters 543 ---------------- 544 membership_type: `aiobungie.internal.enums.MembershipType` 545 The Member ship type, if nothing was passed than it will return all. 546 page: int 547 The page number. Default is `0` 548 limit: int 549 Limit the returned result. Default is `250`. 550 551 Returns 552 ------- 553 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 554 An iterator of the player's activities. 555 556 Raises 557 ------ 558 `aiobungie.MembershipTypeError` 559 The provided membership type was invalid. 560 """ 561 resp = await self.rest.fetch_activities( 562 member_id, 563 character_id, 564 mode, 565 membership_type=membership_type, 566 page=page, 567 limit=limit, 568 ) 569 570 return self.factory.deserialize_activities(resp) 571 572 async def fetch_post_activity(self, instance_id: int, /) -> activity.PostActivity: 573 """Fetch a post activity details. 574 575 Parameters 576 ---------- 577 instance_id: `int` 578 The activity instance id. 579 580 Returns 581 ------- 582 `aiobungie.crates.PostActivity` 583 A post activity object. 584 """ 585 resp = await self.rest.fetch_post_activity(instance_id) 586 587 return self.factory.deserialize_post_activity(resp) 588 589 async def fetch_aggregated_activity_stats( 590 self, 591 character_id: int, 592 membership_id: int, 593 membership_type: typedefs.IntAnd[enums.MembershipType], 594 ) -> iterators.Iterator[activity.AggregatedActivity]: 595 """Fetch aggregated activity stats for a character. 596 597 Parameters 598 ---------- 599 character_id: `int` 600 The id of the character to retrieve the activities for. 601 membership_id: `int` 602 The id of the user that started with `4611`. 603 membership_type: `aiobungie.internal.enums.MembershipType` 604 The Member ship type. 605 606 Returns 607 ------- 608 `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` 609 An iterator of the player's activities. 610 611 Raises 612 ------ 613 `aiobungie.MembershipTypeError` 614 The provided membership type was invalid. 615 """ 616 resp = await self.rest.fetch_aggregated_activity_stats( 617 character_id, membership_id, membership_type 618 ) 619 620 return self.factory.deserialize_aggregated_activities(resp) 621 622 # * Destiny 2 Clans or GroupsV2. 623 624 async def fetch_clan_from_id( 625 self, 626 id: int, 627 /, 628 access_token: typing.Optional[str] = None, 629 ) -> clans.Clan: 630 """Fetch a Bungie Clan by its id. 631 632 Parameters 633 ----------- 634 id: `int` 635 The clan id. 636 637 Returns 638 -------- 639 `aiobungie.crates.Clan` 640 An Bungie clan. 641 642 Raises 643 ------ 644 `aiobungie.NotFound` 645 The clan was not found. 646 """ 647 resp = await self.rest.fetch_clan_from_id(id, access_token) 648 649 return self.factory.deserialize_clan(resp) 650 651 async def fetch_clan( 652 self, 653 name: str, 654 /, 655 access_token: typing.Optional[str] = None, 656 *, 657 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 658 ) -> clans.Clan: 659 """Fetch a Clan by its name. 660 This method will return the first clan found with given name. 661 662 Parameters 663 ---------- 664 name: `str` 665 The clan name 666 667 Other Parameters 668 ---------------- 669 access_token : `typing.Optional[str]` 670 An optional access token to make the request with. 671 672 If the token was bound to a member of the clan, 673 This field `aiobungie.crates.Clan.current_user_membership` will be available 674 and will return the membership of the user who made this request. 675 type : `aiobungie.GroupType` 676 The group type, Default is aiobungie.GroupType.CLAN. 677 678 Returns 679 ------- 680 `aiobungie.crates.Clan` 681 A Bungie clan. 682 683 Raises 684 ------ 685 `aiobungie.NotFound` 686 The clan was not found. 687 """ 688 resp = await self.rest.fetch_clan(name, access_token, type=type) 689 690 return self.factory.deserialize_clan(resp) 691 692 async def fetch_clan_conversations( 693 self, clan_id: int, / 694 ) -> collections.Sequence[clans.ClanConversation]: 695 """Fetch the conversations/chat channels of the given clan id. 696 697 Parameters 698 ---------- 699 clan_id : `int` 700 The clan id. 701 702 Returns 703 `collections.Sequence[aiobungie.crates.ClanConversation]` 704 A sequence of the clan chat channels. 705 """ 706 resp = await self.rest.fetch_clan_conversations(clan_id) 707 708 return self.factory.deserialize_clan_conversations(resp) 709 710 async def fetch_clan_admins( 711 self, clan_id: int, / 712 ) -> iterators.Iterator[clans.ClanMember]: 713 """Fetch the clan founder and admins. 714 715 Parameters 716 ---------- 717 clan_id : `int` 718 The clan id. 719 720 Returns 721 ------- 722 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 723 An iterator over the found clan admins and founder. 724 725 Raises 726 ------ 727 `aiobungie.NotFound` 728 The requested clan was not found. 729 """ 730 resp = await self.rest.fetch_clan_admins(clan_id) 731 732 return self.factory.deserialize_clan_members(resp) 733 734 async def fetch_groups_for_member( 735 self, 736 member_id: int, 737 member_type: typedefs.IntAnd[enums.MembershipType], 738 /, 739 *, 740 filter: int = 0, 741 group_type: enums.GroupType = enums.GroupType.CLAN, 742 ) -> collections.Sequence[clans.GroupMember]: 743 """Fetch information about the groups that a given member has joined. 744 745 Parameters 746 ---------- 747 member_id : `int` 748 The member's id 749 member_type : `aiobungie.MembershipType` 750 The member's membership type. 751 752 Other Parameters 753 ---------------- 754 filter : `int` 755 Filter apply to list of joined groups. This Default to `0` 756 group_type : `aiobungie.GroupType` 757 The group's type. 758 This is always set to `aiobungie.GroupType.CLAN` and should not be changed. 759 760 Returns 761 ------- 762 `collections.Sequence[aiobungie.crates.GroupMember]` 763 A sequence of joined groups for the fetched member. 764 """ 765 resp = await self.rest.fetch_groups_for_member( 766 member_id, member_type, filter=filter, group_type=group_type 767 ) 768 769 return [ 770 self.factory.deserialize_group_member(group) for group in resp["results"] 771 ] 772 773 async def fetch_potential_groups_for_member( 774 self, 775 member_id: int, 776 member_type: typedefs.IntAnd[enums.MembershipType], 777 /, 778 *, 779 filter: int = 0, 780 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 781 ) -> collections.Sequence[clans.GroupMember]: 782 """Fetch the potential groups for a clan member. 783 784 Parameters 785 ---------- 786 member_id : `int` 787 The member's id 788 member_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 789 The member's membership type. 790 791 Other Parameters 792 ---------------- 793 filter : `int` 794 Filter apply to list of joined groups. This Default to `0` 795 group_type : `aiobungie.typedefs.IntAnd[aiobungie.GroupType]` 796 The group's type. 797 This is always set to `aiobungie.GroupType.CLAN` and should not be changed. 798 799 Returns 800 ------- 801 `collections.Sequence[aiobungie.crates.GroupMember]` 802 A sequence of joined potential groups for the fetched member. 803 """ 804 resp = await self.rest.fetch_potential_groups_for_member( 805 member_id, member_type, filter=filter, group_type=group_type 806 ) 807 808 return [ 809 self.factory.deserialize_group_member(group) for group in resp["results"] 810 ] 811 812 async def fetch_clan_members( 813 self, 814 clan_id: int, 815 /, 816 *, 817 name: typing.Optional[str] = None, 818 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 819 ) -> iterators.Iterator[clans.ClanMember]: 820 """Fetch Bungie clan members. 821 822 Parameters 823 ---------- 824 clan_id : `int` 825 The clans id 826 827 Other Parameters 828 ---------------- 829 name : `typing.Optional[str]` 830 If provided, Only players matching this name will be returned. 831 type : `aiobungie.MembershipType` 832 An optional clan member's membership type. 833 This parameter is used to filter the returned results 834 by the provided membership, For an example XBox memberships only, 835 Otherwise will return all memberships. 836 837 Returns 838 ------- 839 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 840 An iterator over the bungie clan members. 841 842 Raises 843 ------ 844 `aiobungie.NotFound` 845 The clan was not found. 846 """ 847 resp = await self.rest.fetch_clan_members(clan_id, type=type, name=name) 848 849 return self.factory.deserialize_clan_members(resp) 850 851 async def fetch_clan_banners(self) -> collections.Sequence[clans.ClanBanner]: 852 """Fetch the clan banners. 853 854 Returns 855 ------- 856 `collections.Sequence[aiobungie.crates.ClanBanner]` 857 A sequence of the clan banners. 858 """ 859 resp = await self.rest.fetch_clan_banners() 860 861 return self.factory.deserialize_clan_banners(resp) 862 863 # This method is required to be here since it deserialize the clan. 864 async def kick_clan_member( 865 self, 866 access_token: str, 867 /, 868 group_id: int, 869 membership_id: int, 870 membership_type: typedefs.IntAnd[enums.MembershipType], 871 ) -> clans.Clan: 872 """Kick a member from the clan. 873 874 .. note:: 875 This request requires OAuth2: oauth2: `AdminGroups` scope. 876 877 Parameters 878 ---------- 879 access_token : `str` 880 The bearer access token associated with the bungie account. 881 group_id: `int` 882 The group id. 883 membership_id : `int` 884 The member id to kick. 885 membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 886 The member's membership type. 887 888 Returns 889 ------- 890 `aiobungie.crates.clan.Clan` 891 The clan that the member was kicked from. 892 """ 893 resp = await self.rest.kick_clan_member( 894 access_token, 895 group_id=group_id, 896 membership_id=membership_id, 897 membership_type=membership_type, 898 ) 899 900 return self.factory.deserialize_clan(resp) 901 902 async def fetch_clan_weekly_rewards(self, clan_id: int) -> milestones.Milestone: 903 """Fetch a Bungie clan's weekly reward state. 904 905 Parameters 906 ---------- 907 clan_id : `int` 908 The clan's id. 909 910 Returns 911 ------- 912 `aiobungie.crates.Milestone` 913 A runtime status of the clan's milestone data. 914 """ 915 916 resp = await self.rest.fetch_clan_weekly_rewards(clan_id) 917 918 return self.factory.deserialize_milestone(resp) 919 920 # * Destiny 2 Entities aka Definitions. 921 922 async def fetch_inventory_item(self, hash: int, /) -> entity.InventoryEntity: 923 """Fetch a static inventory item entity given a its hash. 924 925 Parameters 926 ---------- 927 hash: `int` 928 Inventory item's hash. 929 930 Returns 931 ------- 932 `aiobungie.crates.InventoryEntity` 933 A bungie inventory item. 934 """ 935 resp = await self.rest.fetch_inventory_item(hash) 936 937 return self.factory.deserialize_inventory_entity(resp) 938 939 async def fetch_objective_entity(self, hash: int, /) -> entity.ObjectiveEntity: 940 """Fetch a Destiny objective entity given a its hash. 941 942 Parameters 943 ---------- 944 hash: `int` 945 objective's hash. 946 947 Returns 948 ------- 949 `aiobungie.crates.ObjectiveEntity` 950 An objective entity item. 951 """ 952 resp = await self.rest.fetch_objective_entity(hash) 953 954 return self.factory.deserialize_objective_entity(resp) 955 956 async def search_entities( 957 self, name: str, entity_type: str, *, page: int = 0 958 ) -> iterators.Iterator[entity.SearchableEntity]: 959 """Search for Destiny2 entities given a name and its type. 960 961 Parameters 962 ---------- 963 name : `str` 964 The name of the entity, i.e., Thunderlord, One thousand voices. 965 entity_type : `str` 966 The type of the entity, AKA Definition, 967 For an example `DestinyInventoryItemDefinition` for emblems, weapons, and other inventory items. 968 969 Other Parameters 970 ---------------- 971 page : `int` 972 An optional page to return. Default to 0. 973 974 Returns 975 ------- 976 `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` 977 An iterator over the found results matching the provided name. 978 """ 979 resp = await self.rest.search_entities(name, entity_type, page=page) 980 981 return self.factory.deserialize_inventory_results(resp) 982 983 # Fireteams 984 985 async def fetch_fireteams( 986 self, 987 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 988 *, 989 platform: typedefs.IntAnd[ 990 fireteams.FireteamPlatform 991 ] = fireteams.FireteamPlatform.ANY, 992 language: typing.Union[ 993 fireteams.FireteamLanguage, str 994 ] = fireteams.FireteamLanguage.ALL, 995 date_range: int = 0, 996 page: int = 0, 997 slots_filter: int = 0, 998 ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]: 999 """Fetch public Bungie fireteams with open slots. 1000 1001 Parameters 1002 ---------- 1003 activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]` 1004 The fireteam activity type. 1005 1006 Other Parameters 1007 ---------------- 1008 platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]` 1009 If this is provided. Then the results will be filtered with the given platform. 1010 Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms. 1011 language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]` 1012 A locale language to filter the used language in that fireteam. 1013 Defaults to `aiobungie.crates.FireteamLanguage.ALL` 1014 date_range : `int` 1015 An integer to filter the date range of the returned fireteams. Defaults to `aiobungie.FireteamDate.ALL`. 1016 page : `int` 1017 The page number. By default its `0` which returns all available activities. 1018 slots_filter : `int` 1019 Filter the returned fireteams based on available slots. Default is `0` 1020 1021 Returns 1022 ------- 1023 `typing.Optional[collections.Sequence[fireteams.Fireteam]]` 1024 A sequence of `aiobungie.crates.Fireteam` or `None`. 1025 """ 1026 1027 resp = await self.rest.fetch_fireteams( 1028 activity_type, 1029 platform=platform, 1030 language=language, 1031 date_range=date_range, 1032 page=page, 1033 slots_filter=slots_filter, 1034 ) 1035 1036 return self.factory.deserialize_fireteams(resp) 1037 1038 async def fetch_avaliable_clan_fireteams( 1039 self, 1040 access_token: str, 1041 group_id: int, 1042 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1043 *, 1044 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1045 language: typing.Union[fireteams.FireteamLanguage, str], 1046 date_range: int = 0, 1047 page: int = 0, 1048 public_only: bool = False, 1049 slots_filter: int = 0, 1050 ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]: 1051 """Fetch a clan's fireteams with open slots. 1052 1053 .. note:: 1054 This method requires OAuth2: ReadGroups scope. 1055 1056 Parameters 1057 ---------- 1058 access_token : `str` 1059 The bearer access token associated with the bungie account. 1060 group_id : `int` 1061 The group/clan id of the fireteam. 1062 activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]` 1063 The fireteam activity type. 1064 1065 Other Parameters 1066 ---------------- 1067 platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]` 1068 If this is provided. Then the results will be filtered with the given platform. 1069 Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms. 1070 language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]` 1071 A locale language to filter the used language in that fireteam. 1072 Defaults to `aiobungie.crates.FireteamLanguage.ALL` 1073 date_range : `int` 1074 An integer to filter the date range of the returned fireteams. Defaults to `0`. 1075 page : `int` 1076 The page number. By default its `0` which returns all available activities. 1077 public_only: `bool` 1078 If set to True, Then only public fireteams will be returned. 1079 slots_filter : `int` 1080 Filter the returned fireteams based on available slots. Default is `0` 1081 1082 Returns 1083 ------- 1084 `typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]` 1085 A sequence of fireteams found in the clan. 1086 `None` will be returned if nothing was found. 1087 """ 1088 resp = await self.rest.fetch_avaliable_clan_fireteams( 1089 access_token, 1090 group_id, 1091 activity_type, 1092 platform=platform, 1093 language=language, 1094 date_range=date_range, 1095 page=page, 1096 public_only=public_only, 1097 slots_filter=slots_filter, 1098 ) 1099 1100 return self.factory.deserialize_fireteams(resp) 1101 1102 async def fetch_clan_fireteam( 1103 self, access_token: str, fireteam_id: int, group_id: int 1104 ) -> fireteams.AvailableFireteam: 1105 """Fetch a specific clan fireteam. 1106 1107 .. note:: 1108 This method requires OAuth2: ReadGroups scope. 1109 1110 Parameters 1111 ---------- 1112 access_token : `str` 1113 The bearer access token associated with the bungie account. 1114 group_id : `int` 1115 The group/clan id to fetch the fireteam from. 1116 fireteam_id : `int` 1117 The fireteam id to fetch. 1118 1119 Returns 1120 ------- 1121 `typing.Optional[aiobungie.crates.AvailableFireteam]` 1122 A sequence of available fireteams objects if exists. else `None` will be returned. 1123 """ 1124 resp = await self.rest.fetch_clan_fireteam(access_token, fireteam_id, group_id) 1125 1126 return self.factory.deserialize_available_fireteams( 1127 resp, no_results=True 1128 ) # type: ignore[return-value] 1129 1130 async def fetch_my_clan_fireteams( 1131 self, 1132 access_token: str, 1133 group_id: int, 1134 *, 1135 include_closed: bool = True, 1136 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1137 language: typing.Union[fireteams.FireteamLanguage, str], 1138 filtered: bool = True, 1139 page: int = 0, 1140 ) -> collections.Sequence[fireteams.AvailableFireteam]: 1141 """A method that's similar to `fetch_fireteams` but requires OAuth2. 1142 1143 .. note:: 1144 This method requires OAuth2: ReadGroups scope. 1145 1146 Parameters 1147 ---------- 1148 access_token : str 1149 The bearer access token associated with the bungie account. 1150 group_id : int 1151 The group/clan id to fetch. 1152 1153 Other Parameters 1154 ---------------- 1155 include_closed : bool 1156 If provided and set to True, It will also return closed fireteams. 1157 If provided and set to False, It will only return public fireteams. Default is True. 1158 platform : aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform] 1159 If this is provided. Then the results will be filtered with the given platform. 1160 Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms. 1161 language : typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str] 1162 A locale language to filter the used language in that fireteam. 1163 Defaults to aiobungie.crates.FireteamLanguage.ALL 1164 filtered : bool 1165 If set to True, it will filter by clan. Otherwise not. Default is True. 1166 page : int 1167 The page number. By default its 0 which returns all available activities. 1168 1169 Returns 1170 ------- 1171 `collections.Sequence[aiobungie.crates.AvailableFireteam]` 1172 A sequence of available fireteams objects if exists. else `None` will be returned. 1173 """ 1174 resp = await self.rest.fetch_my_clan_fireteams( 1175 access_token, 1176 group_id, 1177 include_closed=include_closed, 1178 platform=platform, 1179 language=language, 1180 filtered=filtered, 1181 page=page, 1182 ) 1183 1184 return self.factory.deserialize_available_fireteams(resp) # type: ignore[return-value] 1185 1186 # Friends and social. 1187 1188 async def fetch_friends( 1189 self, access_token: str, / 1190 ) -> collections.Sequence[friends.Friend]: 1191 """Fetch bungie friend list. 1192 1193 .. note:: 1194 This requests OAuth2: ReadUserData scope. 1195 1196 Parameters 1197 ----------- 1198 access_token : `str` 1199 The bearer access token associated with the bungie account. 1200 1201 Returns 1202 ------- 1203 `collections.Sequence[aiobungie.crates.Friend]` 1204 A sequence of the friends associated with that access token. 1205 """ 1206 1207 resp = await self.rest.fetch_friends(access_token) 1208 1209 return self.factory.deserialize_friends(resp) 1210 1211 async def fetch_friend_requests( 1212 self, access_token: str, / 1213 ) -> friends.FriendRequestView: 1214 """Fetch pending bungie friend requests queue. 1215 1216 .. note:: 1217 This requests OAuth2: ReadUserData scope. 1218 1219 Parameters 1220 ----------- 1221 access_token : `str` 1222 The bearer access token associated with the bungie account. 1223 1224 Returns 1225 ------- 1226 `aiobungie.crates.FriendRequestView` 1227 A friend requests view of that associated access token. 1228 """ 1229 1230 resp = await self.rest.fetch_friend_requests(access_token) 1231 1232 return self.factory.deserialize_friend_requests(resp) 1233 1234 # Applications and Developer portal. 1235 1236 async def fetch_application(self, appid: int, /) -> application.Application: 1237 """Fetch a Bungie application. 1238 1239 Parameters 1240 ----------- 1241 appid: `int` 1242 The application id. 1243 1244 Returns 1245 -------- 1246 `aiobungie.crates.Application` 1247 A Bungie application. 1248 """ 1249 resp = await self.rest.fetch_application(appid) 1250 1251 return self.factory.deserialize_app(resp) 1252 1253 # Milestones 1254 1255 async def fetch_public_milestone_content( 1256 self, milestone_hash: int, / 1257 ) -> milestones.MilestoneContent: 1258 """Fetch the milestone content given its hash. 1259 1260 Parameters 1261 ---------- 1262 milestone_hash : `int` 1263 The milestone hash. 1264 1265 Returns 1266 ------- 1267 `aiobungie.crates.milestones.MilestoneContent` 1268 A milestone content object. 1269 """ 1270 resp = await self.rest.fetch_public_milestone_content(milestone_hash) 1271 1272 return self.factory.deserialize_public_milestone_content(resp)
Standard Bungie API client application.
This client deserialize the REST JSON responses using Factory
and returns aiobungie.crates Python object implementations of the responses.
A aiobungie.RESTClient REST client can also be used alone for low-level concepts.
Example
import aiobungie
client = aiobungie.Client('...')
async def main():
async with client.rest:
user = await client.fetch_current_user_memberships('...')
print(user)
Parameters
- token (
str): Your Bungie's API key or Token from the developer's portal.
Other Parameters
- max_retries (
int): The max retries number to retry if the request hit a5xxstatus code. - client_secret (
str | None): An optional application client secret, This is only needed if you're fetching OAuth2 tokens with this client. - client_id (
int | None): An optional application client id, This is only needed if you're fetching OAuth2 tokens with this client.
100 def __init__( 101 self, 102 token: str, 103 /, 104 *, 105 client_secret: typing.Optional[str] = None, 106 client_id: typing.Optional[int] = None, 107 max_retries: int = 4, 108 ) -> None: 109 self._rest = rest_.RESTClient( 110 token, 111 client_secret=client_secret, 112 client_id=client_id, 113 max_retries=max_retries, 114 ) 115 116 self._factory = factory_.Factory(self)
A mutable mapping storage for the user's needs.
134 def run( 135 self, future: collections.Coroutine[typing.Any, None, None], debug: bool = False 136 ) -> None: 137 loop: typing.Final[asyncio.AbstractEventLoop] = helpers.get_or_make_loop() 138 try: 139 if not loop.is_running(): 140 loop.set_debug(debug) 141 loop.run_until_complete(future) 142 143 except Exception as exc: 144 raise RuntimeError(f"Failed to run {future.__qualname__}") from exc 145 146 except KeyboardInterrupt: 147 _LOG.warn("Unexpected Keyboard interrupt. Exiting.") 148 return
Runs a coroutine function until its complete.
This is equivalent to asyncio.get_event_loop().run_until_complete(...)
Parameters
- future (
collections.Coroutine[None, None, None]): A coroutine object. - debug (
bool): Either to enable asyncio debug or not. Disabled by default.
Example
async def main() -> None:
await fetch(...)
# Run the coroutine.
client.run(main())
152 async def fetch_current_user_memberships(self, access_token: str, /) -> user.User: 153 """Fetch and return a user object of the bungie net user associated with account. 154 155 .. warning:: 156 This method requires OAuth2 scope and a Bearer access token. 157 158 Parameters 159 ---------- 160 access_token : `str` 161 A valid Bearer access token for the authorization. 162 163 Returns 164 ------- 165 `aiobungie.crates.user.User` 166 A user object includes the Destiny memberships and Bungie.net user. 167 """ 168 resp = await self.rest.fetch_current_user_memberships(access_token) 169 170 return self.factory.deserialize_user(resp)
Fetch and return a user object of the bungie net user associated with account.
This method requires OAuth2 scope and a Bearer access token.
Parameters
- access_token (
str): A valid Bearer access token for the authorization.
Returns
aiobungie.crates.user.User: A user object includes the Destiny memberships and Bungie.net user.
172 async def fetch_bungie_user(self, id: int, /) -> user.BungieUser: 173 """Fetch a Bungie user by their BungieNet id. 174 175 .. note:: 176 This returns a Bungie user membership only. Take a look at `Client.fetch_membership_from_id` 177 for other memberships. 178 179 Parameters 180 ---------- 181 id: `int` 182 The user id. 183 184 Returns 185 ------- 186 `aiobungie.crates.user.BungieUser` 187 A Bungie user. 188 189 Raises 190 ------ 191 `aiobungie.error.NotFound` 192 The user was not found. 193 """ 194 payload = await self.rest.fetch_bungie_user(id) 195 196 return self.factory.deserialize_bungie_user(payload)
Fetch a Bungie user by their BungieNet id.
This returns a Bungie user membership only. Take a look at Client.fetch_membership_from_id
for other memberships.
Parameters
- id (
int): The user id.
Returns
aiobungie.crates.user.BungieUser: A Bungie user.
Raises
NotFound: The user was not found.
198 async def search_users( 199 self, name: str, / 200 ) -> iterators.Iterator[user.SearchableDestinyUser]: 201 """Search for players and return all players that matches the same name. 202 203 Parameters 204 ---------- 205 name : `buildins.str` 206 The user name. 207 208 Returns 209 ------- 210 `aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]` 211 A sequence of destiny memberships. 212 """ 213 payload = await self.rest.search_users(name) 214 215 return iterators.Iterator( 216 [ 217 self.factory.deserialize_searched_user(user) 218 for user in payload["searchResults"] 219 ] 220 )
Search for players and return all players that matches the same name.
Parameters
- name (
buildins.str): The user name.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.DestinyMembership]: A sequence of destiny memberships.
222 async def fetch_user_themes(self) -> collections.Sequence[user.UserThemes]: 223 """Fetch all available user themes. 224 225 Returns 226 ------- 227 `collections.Sequence[aiobungie.crates.user.UserThemes]` 228 A sequence of user themes. 229 """ 230 data = await self.rest.fetch_user_themes() 231 232 return self.factory.deserialize_user_themes(data)
Fetch all available user themes.
Returns
collections.Sequence[aiobungie.crates.user.UserThemes]: A sequence of user themes.
234 async def fetch_hard_types( 235 self, 236 credential: int, 237 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, 238 /, 239 ) -> user.HardLinkedMembership: 240 """Gets any hard linked membership given a credential. 241 Only works for credentials that are public just `aiobungie.CredentialType.STEAMID` right now. 242 Cross Save aware. 243 244 Parameters 245 ---------- 246 credential: `int` 247 A valid SteamID64 248 type: `aiobungie.CredentialType` 249 The credential type. This must not be changed 250 Since its only credential that works "currently" 251 252 Returns 253 ------- 254 `aiobungie.crates.user.HardLinkedMembership` 255 Information about the hard linked data. 256 """ 257 258 payload = await self.rest.fetch_hardlinked_credentials(credential, type) 259 260 return user.HardLinkedMembership( 261 id=int(payload["membershipId"]), 262 type=enums.MembershipType(payload["membershipType"]), 263 cross_save_type=enums.MembershipType(payload["CrossSaveOverriddenType"]), 264 )
Gets any hard linked membership given a credential.
Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now.
Cross Save aware.
Parameters
- credential (
int): A valid SteamID64 - type (
aiobungie.CredentialType): The credential type. This must not be changed Since its only credential that works "currently"
Returns
aiobungie.crates.user.HardLinkedMembership: Information about the hard linked data.
266 async def fetch_membership_from_id( 267 self, 268 id: int, 269 /, 270 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 271 ) -> user.User: 272 """Fetch Bungie user's memberships from their id. 273 274 Notes 275 ----- 276 * This returns both BungieNet membership and a sequence of the player's DestinyMemberships 277 Which includes Stadia, Xbox, Steam and PSN memberships if the player has them, 278 see `aiobungie.crates.user.DestinyMembership` for more details. 279 * If you only want the bungie user. Consider using `Client.fetch_user` method. 280 281 Parameters 282 ---------- 283 id : `int` 284 The user's id. 285 type : `aiobungie.MembershipType` 286 The user's membership type. 287 288 Returns 289 ------- 290 `aiobungie.crates.User` 291 A Bungie user with their membership types. 292 293 Raises 294 ------ 295 aiobungie.NotFound 296 The requested user was not found. 297 """ 298 payload = await self.rest.fetch_membership_from_id(id, type) 299 300 return self.factory.deserialize_user(payload)
Fetch Bungie user's memberships from their id.
Notes
- This returns both BungieNet membership and a sequence of the player's DestinyMemberships
Which includes Stadia, Xbox, Steam and PSN memberships if the player has them,
see
aiobungie.crates.user.DestinyMembershipfor more details. - If you only want the bungie user. Consider using
Client.fetch_usermethod.
Parameters
- id (
int): The user's id. - type (
aiobungie.MembershipType): The user's membership type.
Returns
aiobungie.crates.User: A Bungie user with their membership types.
Raises
- aiobungie.NotFound: The requested user was not found.
302 async def fetch_user_credentials( 303 self, access_token: str, membership_id: int, / 304 ) -> collections.Sequence[user.UserCredentials]: 305 """Fetch an array of credential types attached to the requested account. 306 307 .. note:: 308 This method require OAuth2 Bearer access token. 309 310 Parameters 311 ---------- 312 access_token : `str` 313 The bearer access token associated with the bungie account. 314 membership_id : `int` 315 The id of the membership to return. 316 317 Returns 318 ------- 319 `collections.Sequence[aiobungie.crates.UserCredentials]` 320 A sequence of the attached user credentials. 321 322 Raises 323 ------ 324 `aiobungie.Unauthorized` 325 The access token was wrong or no access token passed. 326 """ 327 resp = await self.rest.fetch_user_credentials(access_token, membership_id) 328 329 return self.factory.deserialize_user_credentials(resp)
Fetch an array of credential types attached to the requested account.
This method require OAuth2 Bearer access token.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - membership_id (
int): The id of the membership to return.
Returns
collections.Sequence[aiobungie.crates.UserCredentials]: A sequence of the attached user credentials.
Raises
aiobungie.Unauthorized: The access token was wrong or no access token passed.
333 async def fetch_profile( 334 self, 335 member_id: int, 336 type: typedefs.IntAnd[enums.MembershipType], 337 components: list[enums.ComponentType], 338 auth: typing.Optional[str] = None, 339 ) -> components.Component: 340 """ 341 Fetch a bungie profile passing components to the request. 342 343 Parameters 344 ---------- 345 member_id: `int` 346 The member's id. 347 type: `aiobungie.MembershipType` 348 A valid membership type. 349 components : `list[aiobungie.ComponentType]` 350 List of profile components to collect and return. 351 352 Other Parameters 353 ---------------- 354 auth : `typing.Optional[str]` 355 A Bearer access_token to make the request with. 356 This is optional and limited to components that only requires an Authorization token. 357 358 Returns 359 -------- 360 `aiobungie.crates.Component` 361 A Destiny 2 player profile with its components. 362 Only passed components will be available if they exists. Otherwise they will be `None` 363 364 Raises 365 ------ 366 `aiobungie.MembershipTypeError` 367 The provided membership type was invalid. 368 """ 369 data = await self.rest.fetch_profile(member_id, type, components, auth) 370 return self.factory.deserialize_components(data)
Fetch a bungie profile passing components to the request.
Parameters
- member_id (
int): The member's id. - type (
aiobungie.MembershipType): A valid membership type. - components (
list[aiobungie.ComponentType]): List of profile components to collect and return.
Other Parameters
- auth (
typing.Optional[str]): A Bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token.
Returns
aiobungie.crates.Component: A Destiny 2 player profile with its components. Only passed components will be available if they exists. Otherwise they will beNone
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
372 async def fetch_linked_profiles( 373 self, 374 member_id: int, 375 member_type: typedefs.IntAnd[enums.MembershipType], 376 /, 377 *, 378 all: bool = False, 379 ) -> profile.LinkedProfile: 380 """Returns a summary information about all profiles linked to the requested member. 381 382 The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships. 383 384 .. note:: 385 It will only return linked accounts whose linkages you are allowed to view. 386 387 Parameters 388 ---------- 389 member_id : `int` 390 The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID. 391 member_type : `aiobungie.MembershipType` 392 The type for the membership whose linked Destiny account you want to return. 393 394 Other Parameters 395 ---------------- 396 all : `bool` 397 If provided and set to `True`, All memberships regardless 398 of whether they're obscured by overrides will be returned, 399 400 If provided and set to `False`, Only available memberships will be returned. 401 The default for this is `False`. 402 403 Returns 404 ------- 405 `aiobungie.crates.profile.LinkedProfile` 406 A linked profile object. 407 """ 408 resp = await self.rest.fetch_linked_profiles(member_id, member_type, all=all) 409 410 return self.factory.deserialize_linked_profiles(resp)
Returns a summary information about all profiles linked to the requested member.
The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.
It will only return linked accounts whose linkages you are allowed to view.
Parameters
- member_id (
int): The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID. - member_type (
aiobungie.MembershipType): The type for the membership whose linked Destiny account you want to return.
Other Parameters
all (
bool): If provided and set toTrue, All memberships regardless of whether they're obscured by overrides will be returned,If provided and set to
False, Only available memberships will be returned. The default for this isFalse.
Returns
aiobungie.crates.profile.LinkedProfile: A linked profile object.
412 async def fetch_player( 413 self, 414 name: str, 415 code: int, 416 /, 417 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, 418 ) -> collections.Sequence[user.DestinyMembership]: 419 """Fetch a Destiny 2 player's memberships. 420 421 Parameters 422 ----------- 423 name: `str` 424 The unique Bungie player name. 425 code : `int` 426 The unique Bungie display name code. 427 type: `aiobungie.internal.enums.MembershipType` 428 The player's membership type, e,g. XBOX, STEAM, PSN 429 430 Returns 431 -------- 432 `collections.Sequence[aiobungie.crates.DestinyMembership]` 433 A sequence of the found Destiny 2 player memberships. 434 An empty sequence will be returned if no one found. 435 436 Raises 437 ------ 438 `aiobungie.MembershipTypeError` 439 The provided membership type was invalid. 440 """ 441 resp = await self.rest.fetch_player(name, code, type) 442 443 return self.factory.deserialize_destiny_memberships(resp)
Fetch a Destiny 2 player's memberships.
Parameters
- name (
str): The unique Bungie player name. - code (
int): The unique Bungie display name code. - type (
MembershipType): The player's membership type, e,g. XBOX, STEAM, PSN
Returns
collections.Sequence[aiobungie.crates.DestinyMembership]: A sequence of the found Destiny 2 player memberships. An empty sequence will be returned if no one found.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
445 async def fetch_character( 446 self, 447 member_id: int, 448 membership_type: typedefs.IntAnd[enums.MembershipType], 449 character_id: int, 450 components: list[enums.ComponentType], 451 auth: typing.Optional[str] = None, 452 ) -> components.CharacterComponent: 453 """Fetch a Destiny 2 character. 454 455 Parameters 456 ---------- 457 member_id: `int` 458 A valid bungie member id. 459 character_id: `int` 460 The Destiny character id to retrieve. 461 membership_type: `aiobungie.internal.enums.MembershipType` 462 The member's membership type. 463 components: `list[aiobungie.ComponentType]` 464 Multiple arguments of character components to collect and return. 465 466 Other Parameters 467 ---------------- 468 auth : `typing.Optional[str]` 469 A Bearer access_token to make the request with. 470 This is optional and limited to components that only requires an Authorization token. 471 472 Returns 473 ------- 474 `aiobungie.crates.CharacterComponent` 475 A Bungie character component. 476 477 `aiobungie.MembershipTypeError` 478 The provided membership type was invalid. 479 """ 480 resp = await self.rest.fetch_character( 481 member_id, membership_type, character_id, components, auth 482 ) 483 484 return self.factory.deserialize_character_component(resp)
Fetch a Destiny 2 character.
Parameters
- member_id (
int): A valid bungie member id. - character_id (
int): The Destiny character id to retrieve. - membership_type (
MembershipType): The member's membership type. - components (
list[aiobungie.ComponentType]): Multiple arguments of character components to collect and return.
Other Parameters
- auth (
typing.Optional[str]): A Bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token.
Returns
aiobungie.crates.CharacterComponent: A Bungie character component.aiobungie.MembershipTypeError: The provided membership type was invalid.
486 async def fetch_unique_weapon_history( 487 self, 488 membership_id: int, 489 character_id: int, 490 membership_type: typedefs.IntAnd[enums.MembershipType], 491 ) -> collections.Sequence[activity.ExtendedWeaponValues]: 492 """Fetch details about unique weapon usage for a character. Includes all exotics. 493 494 Parameters 495 ---------- 496 membership_id : `int` 497 The Destiny user membership id. 498 character_id : `int` 499 The character id to retrieve. 500 membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 501 The Destiny user's membership type. 502 503 Returns 504 ------- 505 `collections.Sequence[aiobungie.crates.ExtendedWeaponValues]` 506 A sequence of the weapon's extended values. 507 """ 508 resp = await self._rest.fetch_unique_weapon_history( 509 membership_id, character_id, membership_type 510 ) 511 512 return [ 513 self._factory.deserialize_extended_weapon_values(weapon) 514 for weapon in resp["weapons"] 515 ]
Fetch details about unique weapon usage for a character. Includes all exotics.
Parameters
- membership_id (
int): The Destiny user membership id. - character_id (
int): The character id to retrieve. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny user's membership type.
Returns
collections.Sequence[aiobungie.crates.ExtendedWeaponValues]: A sequence of the weapon's extended values.
519 async def fetch_activities( 520 self, 521 member_id: int, 522 character_id: int, 523 mode: typedefs.IntAnd[enums.GameMode], 524 *, 525 membership_type: typedefs.IntAnd[ 526 enums.MembershipType 527 ] = enums.MembershipType.ALL, 528 page: int = 0, 529 limit: int = 250, 530 ) -> iterators.Iterator[activity.Activity]: 531 """Fetch a Destiny 2 activity for the specified character id. 532 533 Parameters 534 ---------- 535 member_id: `int` 536 The user id that starts with `4611`. 537 character_id: `int` 538 The id of the character to retrieve the activities for. 539 mode: `aiobungie.typedefs.IntAnd[aiobungie.internal.enums.GameMode]` 540 This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc. 541 542 Other Parameters 543 ---------------- 544 membership_type: `aiobungie.internal.enums.MembershipType` 545 The Member ship type, if nothing was passed than it will return all. 546 page: int 547 The page number. Default is `0` 548 limit: int 549 Limit the returned result. Default is `250`. 550 551 Returns 552 ------- 553 `aiobungie.iterators.Iterator[aiobungie.crates.Activity]` 554 An iterator of the player's activities. 555 556 Raises 557 ------ 558 `aiobungie.MembershipTypeError` 559 The provided membership type was invalid. 560 """ 561 resp = await self.rest.fetch_activities( 562 member_id, 563 character_id, 564 mode, 565 membership_type=membership_type, 566 page=page, 567 limit=limit, 568 ) 569 570 return self.factory.deserialize_activities(resp)
Fetch a Destiny 2 activity for the specified character id.
Parameters
- member_id (
int): The user id that starts with4611. - character_id (
int): The id of the character to retrieve the activities for. - mode (
aiobungie.typedefs.IntAnd[GameMode]): This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc.
Other Parameters
- membership_type (
MembershipType): The Member ship type, if nothing was passed than it will return all. - page (int):
The page number. Default is
0 - limit (int):
Limit the returned result. Default is
250.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.Activity]: An iterator of the player's activities.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
572 async def fetch_post_activity(self, instance_id: int, /) -> activity.PostActivity: 573 """Fetch a post activity details. 574 575 Parameters 576 ---------- 577 instance_id: `int` 578 The activity instance id. 579 580 Returns 581 ------- 582 `aiobungie.crates.PostActivity` 583 A post activity object. 584 """ 585 resp = await self.rest.fetch_post_activity(instance_id) 586 587 return self.factory.deserialize_post_activity(resp)
Fetch a post activity details.
Parameters
- instance_id (
int): The activity instance id.
Returns
aiobungie.crates.PostActivity: A post activity object.
589 async def fetch_aggregated_activity_stats( 590 self, 591 character_id: int, 592 membership_id: int, 593 membership_type: typedefs.IntAnd[enums.MembershipType], 594 ) -> iterators.Iterator[activity.AggregatedActivity]: 595 """Fetch aggregated activity stats for a character. 596 597 Parameters 598 ---------- 599 character_id: `int` 600 The id of the character to retrieve the activities for. 601 membership_id: `int` 602 The id of the user that started with `4611`. 603 membership_type: `aiobungie.internal.enums.MembershipType` 604 The Member ship type. 605 606 Returns 607 ------- 608 `aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]` 609 An iterator of the player's activities. 610 611 Raises 612 ------ 613 `aiobungie.MembershipTypeError` 614 The provided membership type was invalid. 615 """ 616 resp = await self.rest.fetch_aggregated_activity_stats( 617 character_id, membership_id, membership_type 618 ) 619 620 return self.factory.deserialize_aggregated_activities(resp)
Fetch aggregated activity stats for a character.
Parameters
- character_id (
int): The id of the character to retrieve the activities for. - membership_id (
int): The id of the user that started with4611. - membership_type (
MembershipType): The Member ship type.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]: An iterator of the player's activities.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
624 async def fetch_clan_from_id( 625 self, 626 id: int, 627 /, 628 access_token: typing.Optional[str] = None, 629 ) -> clans.Clan: 630 """Fetch a Bungie Clan by its id. 631 632 Parameters 633 ----------- 634 id: `int` 635 The clan id. 636 637 Returns 638 -------- 639 `aiobungie.crates.Clan` 640 An Bungie clan. 641 642 Raises 643 ------ 644 `aiobungie.NotFound` 645 The clan was not found. 646 """ 647 resp = await self.rest.fetch_clan_from_id(id, access_token) 648 649 return self.factory.deserialize_clan(resp)
Fetch a Bungie Clan by its id.
Parameters
- id (
int): The clan id.
Returns
aiobungie.crates.Clan: An Bungie clan.
Raises
aiobungie.NotFound: The clan was not found.
651 async def fetch_clan( 652 self, 653 name: str, 654 /, 655 access_token: typing.Optional[str] = None, 656 *, 657 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 658 ) -> clans.Clan: 659 """Fetch a Clan by its name. 660 This method will return the first clan found with given name. 661 662 Parameters 663 ---------- 664 name: `str` 665 The clan name 666 667 Other Parameters 668 ---------------- 669 access_token : `typing.Optional[str]` 670 An optional access token to make the request with. 671 672 If the token was bound to a member of the clan, 673 This field `aiobungie.crates.Clan.current_user_membership` will be available 674 and will return the membership of the user who made this request. 675 type : `aiobungie.GroupType` 676 The group type, Default is aiobungie.GroupType.CLAN. 677 678 Returns 679 ------- 680 `aiobungie.crates.Clan` 681 A Bungie clan. 682 683 Raises 684 ------ 685 `aiobungie.NotFound` 686 The clan was not found. 687 """ 688 resp = await self.rest.fetch_clan(name, access_token, type=type) 689 690 return self.factory.deserialize_clan(resp)
Fetch a Clan by its name. This method will return the first clan found with given name.
Parameters
- name (
str): The clan name
Other Parameters
access_token (
typing.Optional[str]): An optional access token to make the request with.If the token was bound to a member of the clan, This field
aiobungie.crates.Clan.current_user_membershipwill be available and will return the membership of the user who made this request.- type (
aiobungie.GroupType): The group type, Default is aiobungie.GroupType.CLAN.
Returns
aiobungie.crates.Clan: A Bungie clan.
Raises
aiobungie.NotFound: The clan was not found.
692 async def fetch_clan_conversations( 693 self, clan_id: int, / 694 ) -> collections.Sequence[clans.ClanConversation]: 695 """Fetch the conversations/chat channels of the given clan id. 696 697 Parameters 698 ---------- 699 clan_id : `int` 700 The clan id. 701 702 Returns 703 `collections.Sequence[aiobungie.crates.ClanConversation]` 704 A sequence of the clan chat channels. 705 """ 706 resp = await self.rest.fetch_clan_conversations(clan_id) 707 708 return self.factory.deserialize_clan_conversations(resp)
Fetch the conversations/chat channels of the given clan id.
Parameters
- clan_id (
int): The clan id. - Returns
collections.Sequence[aiobungie.crates.ClanConversation]: A sequence of the clan chat channels.
710 async def fetch_clan_admins( 711 self, clan_id: int, / 712 ) -> iterators.Iterator[clans.ClanMember]: 713 """Fetch the clan founder and admins. 714 715 Parameters 716 ---------- 717 clan_id : `int` 718 The clan id. 719 720 Returns 721 ------- 722 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 723 An iterator over the found clan admins and founder. 724 725 Raises 726 ------ 727 `aiobungie.NotFound` 728 The requested clan was not found. 729 """ 730 resp = await self.rest.fetch_clan_admins(clan_id) 731 732 return self.factory.deserialize_clan_members(resp)
Fetch the clan founder and admins.
Parameters
- clan_id (
int): The clan id.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]: An iterator over the found clan admins and founder.
Raises
aiobungie.NotFound: The requested clan was not found.
734 async def fetch_groups_for_member( 735 self, 736 member_id: int, 737 member_type: typedefs.IntAnd[enums.MembershipType], 738 /, 739 *, 740 filter: int = 0, 741 group_type: enums.GroupType = enums.GroupType.CLAN, 742 ) -> collections.Sequence[clans.GroupMember]: 743 """Fetch information about the groups that a given member has joined. 744 745 Parameters 746 ---------- 747 member_id : `int` 748 The member's id 749 member_type : `aiobungie.MembershipType` 750 The member's membership type. 751 752 Other Parameters 753 ---------------- 754 filter : `int` 755 Filter apply to list of joined groups. This Default to `0` 756 group_type : `aiobungie.GroupType` 757 The group's type. 758 This is always set to `aiobungie.GroupType.CLAN` and should not be changed. 759 760 Returns 761 ------- 762 `collections.Sequence[aiobungie.crates.GroupMember]` 763 A sequence of joined groups for the fetched member. 764 """ 765 resp = await self.rest.fetch_groups_for_member( 766 member_id, member_type, filter=filter, group_type=group_type 767 ) 768 769 return [ 770 self.factory.deserialize_group_member(group) for group in resp["results"] 771 ]
Fetch information about the groups that a given member has joined.
Parameters
- member_id (
int): The member's id - member_type (
aiobungie.MembershipType): The member's membership type.
Other Parameters
- filter (
int): Filter apply to list of joined groups. This Default to0 - group_type (
aiobungie.GroupType): The group's type. This is always set toaiobungie.GroupType.CLANand should not be changed.
Returns
collections.Sequence[aiobungie.crates.GroupMember]: A sequence of joined groups for the fetched member.
773 async def fetch_potential_groups_for_member( 774 self, 775 member_id: int, 776 member_type: typedefs.IntAnd[enums.MembershipType], 777 /, 778 *, 779 filter: int = 0, 780 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 781 ) -> collections.Sequence[clans.GroupMember]: 782 """Fetch the potential groups for a clan member. 783 784 Parameters 785 ---------- 786 member_id : `int` 787 The member's id 788 member_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 789 The member's membership type. 790 791 Other Parameters 792 ---------------- 793 filter : `int` 794 Filter apply to list of joined groups. This Default to `0` 795 group_type : `aiobungie.typedefs.IntAnd[aiobungie.GroupType]` 796 The group's type. 797 This is always set to `aiobungie.GroupType.CLAN` and should not be changed. 798 799 Returns 800 ------- 801 `collections.Sequence[aiobungie.crates.GroupMember]` 802 A sequence of joined potential groups for the fetched member. 803 """ 804 resp = await self.rest.fetch_potential_groups_for_member( 805 member_id, member_type, filter=filter, group_type=group_type 806 ) 807 808 return [ 809 self.factory.deserialize_group_member(group) for group in resp["results"] 810 ]
Fetch the potential groups for a clan member.
Parameters
- member_id (
int): The member's id - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Other Parameters
- filter (
int): Filter apply to list of joined groups. This Default to0 - group_type (
aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. This is always set toaiobungie.GroupType.CLANand should not be changed.
Returns
collections.Sequence[aiobungie.crates.GroupMember]: A sequence of joined potential groups for the fetched member.
812 async def fetch_clan_members( 813 self, 814 clan_id: int, 815 /, 816 *, 817 name: typing.Optional[str] = None, 818 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 819 ) -> iterators.Iterator[clans.ClanMember]: 820 """Fetch Bungie clan members. 821 822 Parameters 823 ---------- 824 clan_id : `int` 825 The clans id 826 827 Other Parameters 828 ---------------- 829 name : `typing.Optional[str]` 830 If provided, Only players matching this name will be returned. 831 type : `aiobungie.MembershipType` 832 An optional clan member's membership type. 833 This parameter is used to filter the returned results 834 by the provided membership, For an example XBox memberships only, 835 Otherwise will return all memberships. 836 837 Returns 838 ------- 839 `aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]` 840 An iterator over the bungie clan members. 841 842 Raises 843 ------ 844 `aiobungie.NotFound` 845 The clan was not found. 846 """ 847 resp = await self.rest.fetch_clan_members(clan_id, type=type, name=name) 848 849 return self.factory.deserialize_clan_members(resp)
Fetch Bungie clan members.
Parameters
- clan_id (
int): The clans id
Other Parameters
- name (
typing.Optional[str]): If provided, Only players matching this name will be returned. - type (
aiobungie.MembershipType): An optional clan member's membership type. This parameter is used to filter the returned results by the provided membership, For an example XBox memberships only, Otherwise will return all memberships.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]: An iterator over the bungie clan members.
Raises
aiobungie.NotFound: The clan was not found.
864 async def kick_clan_member( 865 self, 866 access_token: str, 867 /, 868 group_id: int, 869 membership_id: int, 870 membership_type: typedefs.IntAnd[enums.MembershipType], 871 ) -> clans.Clan: 872 """Kick a member from the clan. 873 874 .. note:: 875 This request requires OAuth2: oauth2: `AdminGroups` scope. 876 877 Parameters 878 ---------- 879 access_token : `str` 880 The bearer access token associated with the bungie account. 881 group_id: `int` 882 The group id. 883 membership_id : `int` 884 The member id to kick. 885 membership_type : `aiobungie.typedefs.IntAnd[aiobungie.MembershipType]` 886 The member's membership type. 887 888 Returns 889 ------- 890 `aiobungie.crates.clan.Clan` 891 The clan that the member was kicked from. 892 """ 893 resp = await self.rest.kick_clan_member( 894 access_token, 895 group_id=group_id, 896 membership_id=membership_id, 897 membership_type=membership_type, 898 ) 899 900 return self.factory.deserialize_clan(resp)
Kick a member from the clan.
This request requires OAuth2: oauth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id. - membership_id (
int): The member id to kick. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Returns
aiobungie.crates.clan.Clan: The clan that the member was kicked from.
902 async def fetch_clan_weekly_rewards(self, clan_id: int) -> milestones.Milestone: 903 """Fetch a Bungie clan's weekly reward state. 904 905 Parameters 906 ---------- 907 clan_id : `int` 908 The clan's id. 909 910 Returns 911 ------- 912 `aiobungie.crates.Milestone` 913 A runtime status of the clan's milestone data. 914 """ 915 916 resp = await self.rest.fetch_clan_weekly_rewards(clan_id) 917 918 return self.factory.deserialize_milestone(resp)
Fetch a Bungie clan's weekly reward state.
Parameters
- clan_id (
int): The clan's id.
Returns
aiobungie.crates.Milestone: A runtime status of the clan's milestone data.
922 async def fetch_inventory_item(self, hash: int, /) -> entity.InventoryEntity: 923 """Fetch a static inventory item entity given a its hash. 924 925 Parameters 926 ---------- 927 hash: `int` 928 Inventory item's hash. 929 930 Returns 931 ------- 932 `aiobungie.crates.InventoryEntity` 933 A bungie inventory item. 934 """ 935 resp = await self.rest.fetch_inventory_item(hash) 936 937 return self.factory.deserialize_inventory_entity(resp)
Fetch a static inventory item entity given a its hash.
Parameters
- hash (
int): Inventory item's hash.
Returns
aiobungie.crates.InventoryEntity: A bungie inventory item.
939 async def fetch_objective_entity(self, hash: int, /) -> entity.ObjectiveEntity: 940 """Fetch a Destiny objective entity given a its hash. 941 942 Parameters 943 ---------- 944 hash: `int` 945 objective's hash. 946 947 Returns 948 ------- 949 `aiobungie.crates.ObjectiveEntity` 950 An objective entity item. 951 """ 952 resp = await self.rest.fetch_objective_entity(hash) 953 954 return self.factory.deserialize_objective_entity(resp)
Fetch a Destiny objective entity given a its hash.
Parameters
- hash (
int): objective's hash.
Returns
aiobungie.crates.ObjectiveEntity: An objective entity item.
956 async def search_entities( 957 self, name: str, entity_type: str, *, page: int = 0 958 ) -> iterators.Iterator[entity.SearchableEntity]: 959 """Search for Destiny2 entities given a name and its type. 960 961 Parameters 962 ---------- 963 name : `str` 964 The name of the entity, i.e., Thunderlord, One thousand voices. 965 entity_type : `str` 966 The type of the entity, AKA Definition, 967 For an example `DestinyInventoryItemDefinition` for emblems, weapons, and other inventory items. 968 969 Other Parameters 970 ---------------- 971 page : `int` 972 An optional page to return. Default to 0. 973 974 Returns 975 ------- 976 `aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]` 977 An iterator over the found results matching the provided name. 978 """ 979 resp = await self.rest.search_entities(name, entity_type, page=page) 980 981 return self.factory.deserialize_inventory_results(resp)
Search for Destiny2 entities given a name and its type.
Parameters
- name (
str): The name of the entity, i.e., Thunderlord, One thousand voices. - entity_type (
str): The type of the entity, AKA Definition, For an exampleDestinyInventoryItemDefinitionfor emblems, weapons, and other inventory items.
Other Parameters
- page (
int): An optional page to return. Default to 0.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]: An iterator over the found results matching the provided name.
985 async def fetch_fireteams( 986 self, 987 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 988 *, 989 platform: typedefs.IntAnd[ 990 fireteams.FireteamPlatform 991 ] = fireteams.FireteamPlatform.ANY, 992 language: typing.Union[ 993 fireteams.FireteamLanguage, str 994 ] = fireteams.FireteamLanguage.ALL, 995 date_range: int = 0, 996 page: int = 0, 997 slots_filter: int = 0, 998 ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]: 999 """Fetch public Bungie fireteams with open slots. 1000 1001 Parameters 1002 ---------- 1003 activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]` 1004 The fireteam activity type. 1005 1006 Other Parameters 1007 ---------------- 1008 platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]` 1009 If this is provided. Then the results will be filtered with the given platform. 1010 Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms. 1011 language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]` 1012 A locale language to filter the used language in that fireteam. 1013 Defaults to `aiobungie.crates.FireteamLanguage.ALL` 1014 date_range : `int` 1015 An integer to filter the date range of the returned fireteams. Defaults to `aiobungie.FireteamDate.ALL`. 1016 page : `int` 1017 The page number. By default its `0` which returns all available activities. 1018 slots_filter : `int` 1019 Filter the returned fireteams based on available slots. Default is `0` 1020 1021 Returns 1022 ------- 1023 `typing.Optional[collections.Sequence[fireteams.Fireteam]]` 1024 A sequence of `aiobungie.crates.Fireteam` or `None`. 1025 """ 1026 1027 resp = await self.rest.fetch_fireteams( 1028 activity_type, 1029 platform=platform, 1030 language=language, 1031 date_range=date_range, 1032 page=page, 1033 slots_filter=slots_filter, 1034 ) 1035 1036 return self.factory.deserialize_fireteams(resp)
Fetch public Bungie fireteams with open slots.
Parameters
- activity_type (
aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): The fireteam activity type.
Other Parameters
- platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - date_range (
int): An integer to filter the date range of the returned fireteams. Defaults toaiobungie.FireteamDate.ALL. - page (
int): The page number. By default its0which returns all available activities. - slots_filter (
int): Filter the returned fireteams based on available slots. Default is0
Returns
typing.Optional[collections.Sequence[fireteams.Fireteam]]: A sequence ofaiobungie.crates.FireteamorNone.
1038 async def fetch_avaliable_clan_fireteams( 1039 self, 1040 access_token: str, 1041 group_id: int, 1042 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1043 *, 1044 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1045 language: typing.Union[fireteams.FireteamLanguage, str], 1046 date_range: int = 0, 1047 page: int = 0, 1048 public_only: bool = False, 1049 slots_filter: int = 0, 1050 ) -> typing.Optional[collections.Sequence[fireteams.Fireteam]]: 1051 """Fetch a clan's fireteams with open slots. 1052 1053 .. note:: 1054 This method requires OAuth2: ReadGroups scope. 1055 1056 Parameters 1057 ---------- 1058 access_token : `str` 1059 The bearer access token associated with the bungie account. 1060 group_id : `int` 1061 The group/clan id of the fireteam. 1062 activity_type : `aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]` 1063 The fireteam activity type. 1064 1065 Other Parameters 1066 ---------------- 1067 platform : `aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform]` 1068 If this is provided. Then the results will be filtered with the given platform. 1069 Defaults to `aiobungie.crates.FireteamPlatform.ANY` which returns all platforms. 1070 language : `typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str]` 1071 A locale language to filter the used language in that fireteam. 1072 Defaults to `aiobungie.crates.FireteamLanguage.ALL` 1073 date_range : `int` 1074 An integer to filter the date range of the returned fireteams. Defaults to `0`. 1075 page : `int` 1076 The page number. By default its `0` which returns all available activities. 1077 public_only: `bool` 1078 If set to True, Then only public fireteams will be returned. 1079 slots_filter : `int` 1080 Filter the returned fireteams based on available slots. Default is `0` 1081 1082 Returns 1083 ------- 1084 `typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]` 1085 A sequence of fireteams found in the clan. 1086 `None` will be returned if nothing was found. 1087 """ 1088 resp = await self.rest.fetch_avaliable_clan_fireteams( 1089 access_token, 1090 group_id, 1091 activity_type, 1092 platform=platform, 1093 language=language, 1094 date_range=date_range, 1095 page=page, 1096 public_only=public_only, 1097 slots_filter=slots_filter, 1098 ) 1099 1100 return self.factory.deserialize_fireteams(resp)
Fetch a clan's fireteams with open slots.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id of the fireteam. - activity_type (
aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): The fireteam activity type.
Other Parameters
- platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - date_range (
int): An integer to filter the date range of the returned fireteams. Defaults to0. - page (
int): The page number. By default its0which returns all available activities. - public_only (
bool): If set to True, Then only public fireteams will be returned. - slots_filter (
int): Filter the returned fireteams based on available slots. Default is0
Returns
typing.Optional[collections.Sequence[aiobungie.crates.Fireteam]]: A sequence of fireteams found in the clan.Nonewill be returned if nothing was found.
1102 async def fetch_clan_fireteam( 1103 self, access_token: str, fireteam_id: int, group_id: int 1104 ) -> fireteams.AvailableFireteam: 1105 """Fetch a specific clan fireteam. 1106 1107 .. note:: 1108 This method requires OAuth2: ReadGroups scope. 1109 1110 Parameters 1111 ---------- 1112 access_token : `str` 1113 The bearer access token associated with the bungie account. 1114 group_id : `int` 1115 The group/clan id to fetch the fireteam from. 1116 fireteam_id : `int` 1117 The fireteam id to fetch. 1118 1119 Returns 1120 ------- 1121 `typing.Optional[aiobungie.crates.AvailableFireteam]` 1122 A sequence of available fireteams objects if exists. else `None` will be returned. 1123 """ 1124 resp = await self.rest.fetch_clan_fireteam(access_token, fireteam_id, group_id) 1125 1126 return self.factory.deserialize_available_fireteams( 1127 resp, no_results=True 1128 ) # type: ignore[return-value]
Fetch a specific clan fireteam.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id to fetch the fireteam from. - fireteam_id (
int): The fireteam id to fetch.
Returns
typing.Optional[aiobungie.crates.AvailableFireteam]: A sequence of available fireteams objects if exists. elseNonewill be returned.
1130 async def fetch_my_clan_fireteams( 1131 self, 1132 access_token: str, 1133 group_id: int, 1134 *, 1135 include_closed: bool = True, 1136 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1137 language: typing.Union[fireteams.FireteamLanguage, str], 1138 filtered: bool = True, 1139 page: int = 0, 1140 ) -> collections.Sequence[fireteams.AvailableFireteam]: 1141 """A method that's similar to `fetch_fireteams` but requires OAuth2. 1142 1143 .. note:: 1144 This method requires OAuth2: ReadGroups scope. 1145 1146 Parameters 1147 ---------- 1148 access_token : str 1149 The bearer access token associated with the bungie account. 1150 group_id : int 1151 The group/clan id to fetch. 1152 1153 Other Parameters 1154 ---------------- 1155 include_closed : bool 1156 If provided and set to True, It will also return closed fireteams. 1157 If provided and set to False, It will only return public fireteams. Default is True. 1158 platform : aiobungie.typedefs.IntAnd[aiobungie.crates.fireteams.FireteamPlatform] 1159 If this is provided. Then the results will be filtered with the given platform. 1160 Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms. 1161 language : typing.Union[aiobungie.crates.fireteams.FireteamLanguage, str] 1162 A locale language to filter the used language in that fireteam. 1163 Defaults to aiobungie.crates.FireteamLanguage.ALL 1164 filtered : bool 1165 If set to True, it will filter by clan. Otherwise not. Default is True. 1166 page : int 1167 The page number. By default its 0 which returns all available activities. 1168 1169 Returns 1170 ------- 1171 `collections.Sequence[aiobungie.crates.AvailableFireteam]` 1172 A sequence of available fireteams objects if exists. else `None` will be returned. 1173 """ 1174 resp = await self.rest.fetch_my_clan_fireteams( 1175 access_token, 1176 group_id, 1177 include_closed=include_closed, 1178 platform=platform, 1179 language=language, 1180 filtered=filtered, 1181 page=page, 1182 ) 1183 1184 return self.factory.deserialize_available_fireteams(resp) # type: ignore[return-value]
A method that's similar to fetch_fireteams but requires OAuth2.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (str): The bearer access token associated with the bungie account.
- group_id (int): The group/clan id to fetch.
Other Parameters
- include_closed (bool): If provided and set to True, It will also return closed fireteams. If provided and set to False, It will only return public fireteams. Default is True.
- platform (aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults to aiobungie.crates.FireteamPlatform.ANY which returns all platforms.
- language (typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults to aiobungie.crates.FireteamLanguage.ALL
- filtered (bool): If set to True, it will filter by clan. Otherwise not. Default is True.
- page (int): The page number. By default its 0 which returns all available activities.
Returns
collections.Sequence[aiobungie.crates.AvailableFireteam]: A sequence of available fireteams objects if exists. elseNonewill be returned.
1188 async def fetch_friends( 1189 self, access_token: str, / 1190 ) -> collections.Sequence[friends.Friend]: 1191 """Fetch bungie friend list. 1192 1193 .. note:: 1194 This requests OAuth2: ReadUserData scope. 1195 1196 Parameters 1197 ----------- 1198 access_token : `str` 1199 The bearer access token associated with the bungie account. 1200 1201 Returns 1202 ------- 1203 `collections.Sequence[aiobungie.crates.Friend]` 1204 A sequence of the friends associated with that access token. 1205 """ 1206 1207 resp = await self.rest.fetch_friends(access_token) 1208 1209 return self.factory.deserialize_friends(resp)
Fetch bungie friend list.
This requests OAuth2: ReadUserData scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
collections.Sequence[aiobungie.crates.Friend]: A sequence of the friends associated with that access token.
1211 async def fetch_friend_requests( 1212 self, access_token: str, / 1213 ) -> friends.FriendRequestView: 1214 """Fetch pending bungie friend requests queue. 1215 1216 .. note:: 1217 This requests OAuth2: ReadUserData scope. 1218 1219 Parameters 1220 ----------- 1221 access_token : `str` 1222 The bearer access token associated with the bungie account. 1223 1224 Returns 1225 ------- 1226 `aiobungie.crates.FriendRequestView` 1227 A friend requests view of that associated access token. 1228 """ 1229 1230 resp = await self.rest.fetch_friend_requests(access_token) 1231 1232 return self.factory.deserialize_friend_requests(resp)
Fetch pending bungie friend requests queue.
This requests OAuth2: ReadUserData scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
aiobungie.crates.FriendRequestView: A friend requests view of that associated access token.
1236 async def fetch_application(self, appid: int, /) -> application.Application: 1237 """Fetch a Bungie application. 1238 1239 Parameters 1240 ----------- 1241 appid: `int` 1242 The application id. 1243 1244 Returns 1245 -------- 1246 `aiobungie.crates.Application` 1247 A Bungie application. 1248 """ 1249 resp = await self.rest.fetch_application(appid) 1250 1251 return self.factory.deserialize_app(resp)
Fetch a Bungie application.
Parameters
- appid (
int): The application id.
Returns
aiobungie.crates.Application: A Bungie application.
1255 async def fetch_public_milestone_content( 1256 self, milestone_hash: int, / 1257 ) -> milestones.MilestoneContent: 1258 """Fetch the milestone content given its hash. 1259 1260 Parameters 1261 ---------- 1262 milestone_hash : `int` 1263 The milestone hash. 1264 1265 Returns 1266 ------- 1267 `aiobungie.crates.milestones.MilestoneContent` 1268 A milestone content object. 1269 """ 1270 resp = await self.rest.fetch_public_milestone_content(milestone_hash) 1271 1272 return self.factory.deserialize_public_milestone_content(resp)
Fetch the milestone content given its hash.
Parameters
- milestone_hash (
int): The milestone hash.
Returns
aiobungie.crates.milestones.MilestoneContent: A milestone content object.
781@typing.final 782class ClosedReasons(Flag): 783 """A Flags enumeration representing the reasons why a person can't join this user's fireteam.""" 784 785 NONE = 0 786 MATCHMAKING = 1 << 0 787 LOADING = 1 << 1 788 SOLO = 1 << 2 789 """The activity is required to be played solo.""" 790 INTERNAL_REASONS = 1 << 3 791 """ 792 The user can't be joined for one of a variety of internal reasons. 793 Basically, the game can't let you join at this time, 794 but for reasons that aren't under the control of this user 795 """ 796 DISALLOWED_BY_GAME_STATE = 1 << 4 797 """The user's current activity/quest/other transitory game state is preventing joining.""" 798 OFFLINE = 32768 799 """The user appears offline."""
A Flags enumeration representing the reasons why a person can't join this user's fireteam.
The user can't be joined for one of a variety of internal reasons. Basically, the game can't let you join at this time, but for reasons that aren't under the control of this user
The user's current activity/quest/other transitory game state is preventing joining.
74@typing.final 75class ComponentFields(enums.Enum): 76 """An enum that provides fields found in a base component response.""" 77 78 PRIVACY = ComponentPrivacy 79 DISABLED = False
An enum that provides fields found in a base component response.
65@typing.final 66class ComponentPrivacy(int, enums.Enum): 67 """An enum the provides privacy settings for profile components.""" 68 69 NONE = 0 70 PUBLIC = 1 71 PRIVATE = 2
An enum the provides privacy settings for profile components.
358@typing.final 359class ComponentType(Enum): 360 """An Enum for Destiny 2 profile Components.""" 361 362 NONE = 0 363 364 PROFILE = 100 365 PROFILE_INVENTORIES = 102 366 PROFILE_CURRENCIES = 103 367 PROFILE_PROGRESSION = 104 368 ALL_PROFILES = ( 369 PROFILE, 370 PROFILE_INVENTORIES, 371 PROFILE_CURRENCIES, 372 PROFILE_PROGRESSION, 373 ) 374 """All profile components.""" 375 376 VENDORS = 400 377 VENDOR_SALES = 402 378 VENDOR_RECEIPTS = 101 379 ALL_VENDORS = (VENDORS, VENDOR_RECEIPTS, VENDOR_SALES) 380 """All vendor components.""" 381 382 # Items 383 ITEM_INSTANCES = 300 384 ITEM_OBJECTIVES = 301 385 ITEM_PERKS = 302 386 ITEM_RENDER_DATA = 303 387 ITEM_STATS = 304 388 ITEM_SOCKETS = 305 389 ITEM_TALENT_GRINDS = 306 390 ITEM_PLUG_STATES = 308 391 ITEM_PLUG_OBJECTIVES = 309 392 ITEM_REUSABLE_PLUGS = 310 393 394 ALL_ITEMS = ( 395 ITEM_PLUG_OBJECTIVES, 396 ITEM_PLUG_STATES, 397 ITEM_SOCKETS, 398 ITEM_INSTANCES, 399 ITEM_OBJECTIVES, 400 ITEM_PERKS, 401 ITEM_RENDER_DATA, 402 ITEM_STATS, 403 ITEM_TALENT_GRINDS, 404 ITEM_REUSABLE_PLUGS, 405 ) 406 """All item components.""" 407 408 PLATFORM_SILVER = 105 409 KIOSKS = 500 410 CURRENCY_LOOKUPS = 600 411 PRESENTATION_NODES = 700 412 COLLECTIBLES = 800 413 RECORDS = 900 414 TRANSITORY = 1000 415 METRICS = 1100 416 INVENTORIES = 102 417 STRING_VARIABLES = 1200 418 CRAFTABLES = 1300 419 420 CHARACTERS = 200 421 CHARACTER_INVENTORY = 201 422 CHARECTER_PROGRESSION = 202 423 CHARACTER_RENDER_DATA = 203 424 CHARACTER_ACTIVITIES = 204 425 CHARACTER_EQUIPMENT = 205 426 CHARACTER_LOADOUTS = 206 427 428 ALL_CHARACTERS = ( 429 CHARACTERS, 430 CHARACTER_INVENTORY, 431 CHARECTER_PROGRESSION, 432 CHARACTER_RENDER_DATA, 433 CHARACTER_ACTIVITIES, 434 CHARACTER_EQUIPMENT, 435 CHARACTER_LOADOUTS, 436 RECORDS, 437 ) 438 """All character components.""" 439 440 ALL = ( 441 *ALL_PROFILES, # type: ignore 442 *ALL_CHARACTERS, # type: ignore 443 *ALL_VENDORS, # type: ignore 444 *ALL_ITEMS, # type: ignore 445 RECORDS, 446 CURRENCY_LOOKUPS, 447 PRESENTATION_NODES, 448 COLLECTIBLES, 449 KIOSKS, 450 METRICS, 451 PLATFORM_SILVER, 452 INVENTORIES, 453 STRING_VARIABLES, 454 TRANSITORY, 455 CRAFTABLES, 456 ) 457 """ALl components included."""
An Enum for Destiny 2 profile Components.
All item components.
All character components.
ALl components included.
663@typing.final 664class CredentialType(int, Enum): 665 """The types of the accounts system supports at bungie.""" 666 667 NONE = 0 668 XUID = 1 669 PSNID = 2 670 WILD = 3 671 FAKE = 4 672 FACEBOOK = 5 673 GOOGLE = 8 674 WINDOWS = 9 675 DEMONID = 10 676 STEAMID = 12 677 BATTLENETID = 14 678 STADIAID = 16 679 TWITCHID = 18
The types of the accounts system supports at bungie.
541@typing.final 542class DamageType(int, Enum): 543 """Enums for Destiny Damage types""" 544 545 NONE = 0 546 KINETIC = 1 547 ARC = 2 548 SOLAR = 3 549 VOID = 4 550 RAID = 5 551 """This is a special damage type reserved for some raid activity encounters.""" 552 STASIS = 6
Enums for Destiny Damage types
This is a special damage type reserved for some raid activity encounters.
64@typing.final 65class Difficulty(int, enums.Enum): 66 """An enum for activities difficulties.""" 67 68 TRIVIAL = 0 69 EASY = 1 70 NORMAL = 2 71 CHALLENGING = 3 72 HARD = 4 73 BRAVE = 5 74 ALMOST_IMPOSSIBLE = 6 75 IMPOSSIBLE = 7
An enum for activities difficulties.
160@typing.final 161class Dungeon(int, Enum): 162 """An Enum for all available Dungeon/Like missions in Destiny 2.""" 163 164 NORMAL_PRESAGE = 2124066889 165 """Normal Presage""" 166 167 MASTER_PRESAGE = 4212753278 168 """Master Presage""" 169 170 HARBINGER = 1738383283 171 """Harbinger""" 172 173 PROPHECY = 4148187374 174 """Prophecy""" 175 176 MASTER_POH = 785700673 177 """Master Pit of Heresy?""" 178 179 LEGEND_POH = 785700678 180 """Legend Pit of Heresy?""" 181 182 POH = 1375089621 183 """Normal Pit of Heresy.""" 184 185 SHATTERED = 2032534090 186 """Shattered Throne""" 187 188 GOA_LEGEND = 4078656646 189 """Grasp of Avarice legend.""" 190 191 GOA_MASTER = 3774021532 192 """Grasp of Avarice master."""
An Enum for all available Dungeon/Like missions in Destiny 2.
72class Enum(__enum.Enum): 73 """Builtin Python enum with extra handlings.""" 74 75 @property 76 def name(self) -> str: # type: ignore[override] 77 return self._name_ 78 79 @property 80 def value(self) -> typing.Any: # type: ignore[override] 81 return self._value_ 82 83 def __str__(self) -> str: 84 return self._name_ 85 86 def __repr__(self) -> str: 87 return f"<{type(self).__name__}.{self._name_}: {self._value_!s}>" 88 89 def __int__(self) -> int: 90 if isinstance(self.value, _ITERABLE): 91 raise TypeError( 92 f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.", 93 ) 94 return int(self.value)
Builtin Python enum with extra handlings.
61class Factory(interfaces.FactoryInterface): 62 """The base deserialization factory class for all aiobungie objects. 63 64 Highly inspired hikari entity factory used to deserialize JSON responses from the REST client and turning them 65 into a `aiobungie.crates` Python classes. 66 """ 67 68 __slots__ = ("_net",) 69 70 def __init__(self, net: traits.Netrunner) -> None: 71 self._net = net 72 73 def deserialize_bungie_user(self, data: typedefs.JSONObject) -> user.BungieUser: 74 return user.BungieUser( 75 id=int(data["membershipId"]), 76 created_at=time.clean_date(data["firstAccess"]), 77 name=data.get("cachedBungieGlobalDisplayName", undefined.UNDEFINED), 78 is_deleted=data["isDeleted"], 79 about=data["about"], 80 updated_at=time.clean_date(data["lastUpdate"]), 81 psn_name=data.get("psnDisplayName", None), 82 stadia_name=data.get("stadiaDisplayName", None), 83 steam_name=data.get("steamDisplayName", None), 84 twitch_name=data.get("twitchDisplayName", None), 85 blizzard_name=data.get("blizzardDisplayName", None), 86 status=data["statusText"], 87 locale=data["locale"], 88 picture=assets.Image(path=str(data["profilePicturePath"])), 89 code=data.get("cachedBungieGlobalDisplayNameCode", None), 90 unique_name=data.get("uniqueName", None), 91 theme_id=int(data["profileTheme"]), 92 show_activity=bool(data["showActivity"]), 93 theme_name=data["profileThemeName"], 94 display_title=data["userTitleDisplay"], 95 ) 96 97 def deserialize_partial_bungie_user( 98 self, payload: typedefs.JSONObject 99 ) -> user.PartialBungieUser: 100 return user.PartialBungieUser( 101 net=self._net, 102 types=[ 103 enums.MembershipType(type_) 104 for type_ in payload.get("applicableMembershipTypes", []) 105 ], 106 name=payload.get("displayName", undefined.UNDEFINED), 107 id=int(payload["membershipId"]), 108 crossave_override=enums.MembershipType(payload["crossSaveOverride"]), 109 is_public=payload["isPublic"], 110 icon=assets.Image(payload.get("iconPath", "")), 111 type=enums.MembershipType(payload["membershipType"]), 112 ) 113 114 def deserialize_destiny_membership( 115 self, payload: typedefs.JSONObject 116 ) -> user.DestinyMembership: 117 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 118 if ( 119 raw_name := payload.get("bungieGlobalDisplayName", "") 120 ) and not typedefs.is_unknown(raw_name): 121 name = raw_name 122 123 return user.DestinyMembership( 124 net=self._net, 125 id=int(payload["membershipId"]), 126 name=name, 127 code=payload.get("bungieGlobalDisplayNameCode", None), 128 last_seen_name=payload.get("LastSeenDisplayName") 129 or payload.get("displayName") # noqa: W503 130 or "", # noqa: W503 131 type=enums.MembershipType(payload["membershipType"]), 132 is_public=payload["isPublic"], 133 crossave_override=enums.MembershipType(payload["crossSaveOverride"]), 134 icon=assets.Image(payload.get("iconPath", "")), 135 types=[ 136 enums.MembershipType(type_) 137 for type_ in payload.get("applicableMembershipTypes", []) 138 ], 139 ) 140 141 def deserialize_destiny_memberships( 142 self, data: typedefs.JSONArray 143 ) -> collections.Sequence[user.DestinyMembership]: 144 return [self.deserialize_destiny_membership(membership) for membership in data] 145 146 def deserialize_user(self, data: typedefs.JSONObject) -> user.User: 147 primary_membership_id: typing.Optional[int] = None 148 if raw_primary_id := data.get("primaryMembershipId"): 149 primary_membership_id = int(raw_primary_id) 150 151 return user.User( 152 bungie=self.deserialize_bungie_user(data["bungieNetUser"]), 153 destiny=self.deserialize_destiny_memberships(data["destinyMemberships"]), 154 primary_membership_id=primary_membership_id, 155 ) 156 157 def deserialize_searched_user( 158 self, payload: typedefs.JSONObject 159 ) -> user.SearchableDestinyUser: 160 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 161 if (raw_name := payload["bungieGlobalDisplayName"]) and not typedefs.is_unknown( 162 raw_name 163 ): 164 name = raw_name 165 166 code: typing.Optional[int] = None 167 if raw_code := payload.get("bungieGlobalDisplayNameCode"): 168 code = int(raw_code) 169 170 bungie_id: typing.Optional[int] = None 171 if raw_bungie_id := payload.get("bungieNetMembershipId"): 172 bungie_id = int(raw_bungie_id) 173 174 return user.SearchableDestinyUser( 175 name=name, 176 code=code, 177 bungie_id=bungie_id, 178 memberships=self.deserialize_destiny_memberships( 179 payload["destinyMemberships"] 180 ), 181 ) 182 183 def deserialize_user_credentials( 184 self, payload: typedefs.JSONArray 185 ) -> collections.Sequence[user.UserCredentials]: 186 return [ 187 user.UserCredentials( 188 type=enums.CredentialType(int(creds["credentialType"])), 189 display_name=creds["credentialDisplayName"], 190 is_public=creds["isPublic"], 191 self_as_string=creds.get("credentialAsString", undefined.UNDEFINED), 192 ) 193 for creds in payload 194 ] 195 196 def deserialize_user_themes( 197 self, payload: typedefs.JSONArray 198 ) -> collections.Sequence[user.UserThemes]: 199 return [ 200 user.UserThemes( 201 id=int(entry["userThemeId"]), 202 name=entry["userThemeName"] 203 if "userThemeName" in entry 204 else undefined.UNDEFINED, 205 description=entry["userThemeDescription"] 206 if "userThemeDescription" in entry 207 else undefined.UNDEFINED, 208 ) 209 for entry in payload 210 ] 211 212 def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan: 213 # This is kinda redundant 214 data = payload 215 216 # This is always outside the details. 217 current_user_map: typing.Optional[ 218 collections.Mapping[str, clans.ClanMember] 219 ] = None 220 if raw_current_user_map := payload.get("currentUserMemberMap"): 221 current_user_map = { 222 membership_type: self.deserialize_clan_member(membership) 223 for membership_type, membership in raw_current_user_map.items() 224 } 225 226 try: 227 data = payload["detail"] 228 except KeyError: 229 pass 230 231 id = data["groupId"] 232 name = data["name"] 233 created_at = data["creationDate"] 234 member_count = data["memberCount"] 235 about = data["about"] 236 motto = data["motto"] 237 is_public = data["isPublic"] 238 banner = assets.Image(str(data["bannerPath"])) 239 avatar = assets.Image(str(data["avatarPath"])) 240 tags = data["tags"] 241 type = data["groupType"] 242 243 features = data["features"] 244 features_obj = clans.ClanFeatures( 245 max_members=features["maximumMembers"], 246 max_membership_types=features["maximumMembershipsOfGroupType"], 247 capabilities=features["capabilities"], 248 membership_types=features["membershipTypes"], 249 invite_permissions=features["invitePermissionOverride"], 250 update_banner_permissions=features["updateBannerPermissionOverride"], 251 update_culture_permissions=features["updateCulturePermissionOverride"], 252 join_level=features["joinLevel"], 253 ) 254 255 information: typedefs.JSONObject = data["clanInfo"] 256 progression: collections.Mapping[int, progressions.Progression] = { 257 int(prog_hash): self.deserialize_progressions(prog) 258 for prog_hash, prog in information["d2ClanProgressions"].items() 259 } 260 261 founder: typedefs.NoneOr[clans.ClanMember] = None 262 if raw_founder := payload.get("founder"): 263 founder = self.deserialize_clan_member(raw_founder) 264 265 return clans.Clan( 266 net=self._net, 267 id=int(id), 268 name=name, 269 type=enums.GroupType(type), 270 created_at=time.clean_date(created_at), 271 member_count=member_count, 272 motto=motto, 273 about=about, 274 is_public=is_public, 275 banner=banner, 276 avatar=avatar, 277 tags=tags, 278 features=features_obj, 279 owner=founder, 280 progressions=progression, 281 call_sign=information["clanCallsign"], 282 banner_data=information["clanBannerData"], 283 chat_security=data["chatSecurity"], 284 conversation_id=int(data["conversationId"]), 285 allow_chat=data["allowChat"], 286 theme=data["theme"], 287 current_user_membership=current_user_map, 288 ) 289 290 def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember: 291 destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"]) 292 return clans.ClanMember( 293 net=self._net, 294 last_seen_name=destiny_user.last_seen_name, 295 id=destiny_user.id, 296 name=destiny_user.name, 297 icon=destiny_user.icon, 298 last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])), 299 group_id=int(data["groupId"]), 300 joined_at=time.clean_date(data["joinDate"]), 301 types=destiny_user.types, 302 is_public=destiny_user.is_public, 303 type=destiny_user.type, 304 code=destiny_user.code, 305 is_online=data["isOnline"], 306 crossave_override=destiny_user.crossave_override, 307 bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"]) 308 if "bungieNetUserInfo" in data 309 else None, 310 member_type=enums.ClanMemberType(int(data["memberType"])), 311 ) 312 313 def deserialize_clan_members( 314 self, data: typedefs.JSONObject, / 315 ) -> iterators.Iterator[clans.ClanMember]: 316 return iterators.Iterator( 317 [self.deserialize_clan_member(member) for member in data["results"]] 318 ) 319 320 def deserialize_group_member( 321 self, payload: typedefs.JSONObject 322 ) -> clans.GroupMember: 323 member = payload["member"] 324 return clans.GroupMember( 325 net=self._net, 326 join_date=time.clean_date(member["joinDate"]), 327 group_id=int(member["groupId"]), 328 member_type=enums.ClanMemberType(member["memberType"]), 329 is_online=member["isOnline"], 330 last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])), 331 inactive_memberships=payload.get("areAllMembershipsInactive", None), 332 member=self.deserialize_destiny_membership(member["destinyUserInfo"]), 333 group=self.deserialize_clan(payload["group"]), 334 ) 335 336 def _deserialize_clan_conversation( 337 self, payload: typedefs.JSONObject 338 ) -> clans.ClanConversation: 339 return clans.ClanConversation( 340 net=self._net, 341 id=int(payload["conversationId"]), 342 group_id=int(payload["groupId"]), 343 name=( 344 payload["chatName"] 345 if not typedefs.is_unknown(payload["chatName"]) 346 else undefined.UNDEFINED 347 ), 348 chat_enabled=payload["chatEnabled"], 349 security=payload["chatSecurity"], 350 ) 351 352 def deserialize_clan_conversations( 353 self, payload: typedefs.JSONArray 354 ) -> collections.Sequence[clans.ClanConversation]: 355 return [self._deserialize_clan_conversation(conv) for conv in payload] 356 357 def deserialize_app_owner( 358 self, payload: typedefs.JSONObject 359 ) -> application.ApplicationOwner: 360 return application.ApplicationOwner( 361 net=self._net, 362 name=payload.get("bungieGlobalDisplayName", undefined.UNDEFINED), 363 id=int(payload["membershipId"]), 364 type=enums.MembershipType(payload["membershipType"]), 365 icon=assets.Image(str(payload["iconPath"])), 366 is_public=payload["isPublic"], 367 code=payload.get("bungieGlobalDisplayNameCode", None), 368 ) 369 370 def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application: 371 return application.Application( 372 id=int(payload["applicationId"]), 373 name=payload["name"], 374 link=payload["link"], 375 status=payload["status"], 376 redirect_url=payload.get("redirectUrl", None), 377 created_at=time.clean_date(str(payload["creationDate"])), 378 published_at=time.clean_date(str(payload["firstPublished"])), 379 owner=self.deserialize_app_owner(payload["team"][0]["user"]), # type: ignore 380 scope=payload.get("scope", undefined.UNDEFINED), 381 ) 382 383 def _set_character_attrs(self, payload: typedefs.JSONObject) -> character.Character: 384 total_time = time.format_played(int(payload["minutesPlayedTotal"]), suffix=True) 385 return character.Character( 386 net=self._net, 387 id=int(payload["characterId"]), 388 gender=enums.Gender(payload["genderType"]), 389 race=enums.Race(payload["raceType"]), 390 class_type=enums.Class(payload["classType"]), 391 emblem=assets.Image(str(payload["emblemBackgroundPath"])), 392 emblem_icon=assets.Image(str(payload["emblemPath"])), 393 emblem_hash=int(payload["emblemHash"]), 394 last_played=time.clean_date(payload["dateLastPlayed"]), 395 total_played_time=total_time, 396 member_id=int(payload["membershipId"]), 397 member_type=enums.MembershipType(payload["membershipType"]), 398 level=payload["baseCharacterLevel"], 399 title_hash=payload.get("titleRecordHash", None), 400 light=payload["light"], 401 stats={enums.Stat(int(k)): v for k, v in payload["stats"].items()}, 402 ) 403 404 def deserialize_profile( 405 self, payload: typedefs.JSONObject, / 406 ) -> typing.Optional[profile.Profile]: 407 if (raw_profile := payload.get("data")) is None: 408 return None 409 410 payload = raw_profile 411 id = int(payload["userInfo"]["membershipId"]) 412 name = payload["userInfo"]["displayName"] 413 is_public = payload["userInfo"]["isPublic"] 414 type = enums.MembershipType(payload["userInfo"]["membershipType"]) 415 last_played = time.clean_date(str(payload["dateLastPlayed"])) 416 character_ids = [int(cid) for cid in payload["characterIds"]] 417 power_cap = payload["currentSeasonRewardPowerCap"] 418 419 return profile.Profile( 420 id=int(id), 421 name=name, 422 is_public=is_public, 423 type=type, 424 last_played=last_played, 425 character_ids=character_ids, 426 power_cap=power_cap, 427 net=self._net, 428 ) 429 430 def deserialize_profile_item( 431 self, payload: typedefs.JSONObject 432 ) -> profile.ProfileItemImpl: 433 instance_id: typing.Optional[int] = None 434 if raw_instance_id := payload.get("itemInstanceId"): 435 instance_id = int(raw_instance_id) 436 437 version_number: typing.Optional[int] = None 438 if raw_version := payload.get("versionNumber"): 439 version_number = int(raw_version) 440 441 transfer_status = enums.TransferStatus(payload["transferStatus"]) 442 443 return profile.ProfileItemImpl( 444 net=self._net, 445 hash=payload["itemHash"], 446 quantity=payload["quantity"], 447 bind_status=enums.ItemBindStatus(payload["bindStatus"]), 448 location=enums.ItemLocation(payload["location"]), 449 bucket=payload["bucketHash"], 450 transfer_status=transfer_status, 451 lockable=payload["lockable"], 452 state=enums.ItemState(payload["state"]), 453 dismantel_permissions=payload["dismantlePermission"], 454 is_wrapper=payload["isWrapper"], 455 instance_id=instance_id, 456 version_number=version_number, 457 ornament_id=payload.get("overrideStyleItemHash"), 458 ) 459 460 def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective: 461 return records.Objective( 462 net=self._net, 463 hash=payload["objectiveHash"], 464 visible=payload["visible"], 465 complete=payload["complete"], 466 completion_value=payload["completionValue"], 467 progress=payload.get("progress"), 468 destination_hash=payload.get("destinationHash"), 469 activity_hash=payload.get("activityHash"), 470 ) 471 472 def deserialize_records( 473 self, 474 payload: typedefs.JSONObject, 475 scores: typing.Optional[records.RecordScores] = None, 476 **nodes: int, 477 ) -> records.Record: 478 objectives: typing.Optional[list[records.Objective]] = None 479 interval_objectives: typing.Optional[list[records.Objective]] = None 480 record_state: typedefs.IntAnd[records.RecordState] 481 482 record_state = records.RecordState(payload["state"]) 483 484 if raw_objs := payload.get("objectives"): 485 objectives = [self.deserialize_objectives(obj) for obj in raw_objs] 486 487 if raw_interval_objs := payload.get("intervalObjectives"): 488 interval_objectives = [ 489 self.deserialize_objectives(obj) for obj in raw_interval_objs 490 ] 491 492 return records.Record( 493 scores=scores, 494 categories_node_hash=nodes.get("categories_hash", undefined.UNDEFINED), 495 seals_node_hash=nodes.get("seals_hash", undefined.UNDEFINED), 496 state=record_state, 497 objectives=objectives, 498 interval_objectives=interval_objectives, 499 redeemed_count=payload.get("intervalsRedeemedCount", 0), 500 completion_times=payload.get("completedCount", None), 501 reward_visibility=payload.get("rewardVisibilty", None), 502 ) 503 504 def deserialize_character_records( 505 self, 506 payload: typedefs.JSONObject, 507 scores: typing.Optional[records.RecordScores] = None, 508 record_hashes: typing.Optional[list[int]] = None, 509 ) -> records.CharacterRecord: 510 record = self.deserialize_records(payload, scores) 511 return records.CharacterRecord( 512 scores=scores, 513 categories_node_hash=record.categories_node_hash, 514 seals_node_hash=record.seals_node_hash, 515 state=record.state, 516 objectives=record.objectives, 517 interval_objectives=record.interval_objectives, 518 redeemed_count=payload.get("intervalsRedeemedCount", 0), 519 completion_times=payload.get("completedCount"), 520 reward_visibility=payload.get("rewardVisibilty"), 521 record_hashes=record_hashes or [], 522 ) 523 524 def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye: 525 return character.Dye( 526 channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"] 527 ) 528 529 def deserialize_character_customization( 530 self, payload: typedefs.JSONObject 531 ) -> character.CustomizationOptions: 532 return character.CustomizationOptions( 533 personality=payload["personality"], 534 face=payload["face"], 535 skin_color=payload["skinColor"], 536 lip_color=payload["lipColor"], 537 eye_color=payload["eyeColor"], 538 hair_colors=payload.get("hairColors", []), 539 feature_colors=payload.get("featureColors", []), 540 decal_color=payload["decalColor"], 541 wear_helmet=payload["wearHelmet"], 542 hair_index=payload["hairIndex"], 543 feature_index=payload["featureIndex"], 544 decal_index=payload["decalIndex"], 545 ) 546 547 def deserialize_character_minimal_equipments( 548 self, payload: typedefs.JSONObject 549 ) -> character.MinimalEquipments: 550 dyes = None 551 if raw_dyes := payload.get("dyes"): 552 if raw_dyes: 553 dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes] 554 return character.MinimalEquipments( 555 net=self._net, item_hash=payload["itemHash"], dyes=dyes 556 ) 557 558 def deserialize_character_render_data( 559 self, payload: typedefs.JSONObject, / 560 ) -> character.RenderedData: 561 return character.RenderedData( 562 net=self._net, 563 customization=self.deserialize_character_customization( 564 payload["customization"] 565 ), 566 custom_dyes=[ 567 self.deserialize_character_dye(dye) 568 for dye in payload["customDyes"] 569 if dye 570 ], 571 equipment=[ 572 self.deserialize_character_minimal_equipments(equipment) 573 for equipment in payload["peerView"]["equipment"] 574 ], 575 ) 576 577 def deserialize_available_activity( 578 self, payload: typedefs.JSONObject 579 ) -> activity.AvailableActivity: 580 return activity.AvailableActivity( 581 hash=payload["activityHash"], 582 is_new=payload["isNew"], 583 is_completed=payload["isCompleted"], 584 is_visible=payload["isVisible"], 585 display_level=payload.get("displayLevel"), 586 recommended_light=payload.get("recommendedLight"), 587 difficulty=activity.Difficulty(payload["difficultyTier"]), 588 can_join=payload["canJoin"], 589 can_lead=payload["canLead"], 590 ) 591 592 def deserialize_character_activity( 593 self, payload: typedefs.JSONObject 594 ) -> activity.CharacterActivity: 595 current_mode: typing.Optional[enums.GameMode] = None 596 if raw_current_mode := payload.get("currentActivityModeType"): 597 current_mode = enums.GameMode(raw_current_mode) 598 599 current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None 600 if raw_current_modes := payload.get("currentActivityModeTypes"): 601 current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes] 602 603 return activity.CharacterActivity( 604 date_started=time.clean_date(payload["dateActivityStarted"]), 605 current_hash=payload["currentActivityHash"], 606 current_mode_hash=payload["currentActivityModeHash"], 607 current_mode=current_mode, 608 current_mode_hashes=payload.get("currentActivityModeHashes"), 609 current_mode_types=current_mode_types, 610 current_playlist_hash=payload.get("currentPlaylistActivityHash"), 611 last_story_hash=payload["lastCompletedStoryHash"], 612 available_activities=[ 613 self.deserialize_available_activity(activity_) 614 for activity_ in payload["availableActivities"] 615 ], 616 ) 617 618 def deserialize_profile_items( 619 self, payload: typedefs.JSONObject, / 620 ) -> list[profile.ProfileItemImpl]: 621 return [self.deserialize_profile_item(item) for item in payload["items"]] 622 623 def _deserialize_node(self, payload: typedefs.JSONObject) -> records.Node: 624 return records.Node( 625 state=int(payload["state"]), 626 objective=self.deserialize_objectives(payload["objective"]) 627 if "objective" in payload 628 else None, 629 progress_value=int(payload["progressValue"]), 630 completion_value=int(payload["completionValue"]), 631 record_category_score=int(payload["recordCategoryScore"]) 632 if "recordCategoryScore" in payload 633 else None, 634 ) 635 636 @staticmethod 637 def _deserialize_collectible(payload: typedefs.JSONObject) -> items.Collectible: 638 recent_collectibles: typing.Optional[collections.Collection[int]] = None 639 if raw_recent_collectibles := payload.get("recentCollectibleHashes"): 640 recent_collectibles = [ 641 int(item_hash) for item_hash in raw_recent_collectibles 642 ] 643 644 collectibles: dict[int, int] = {} 645 for item_hash, mapping in payload["collectibles"].items(): 646 collectibles[int(item_hash)] = int(mapping["state"]) 647 648 return items.Collectible( 649 recent_collectibles=recent_collectibles, 650 collectibles=collectibles, 651 collection_categorie_hash=int(payload["collectionCategoriesRootNodeHash"]), 652 collection_badges_hash=int(payload["collectionBadgesRootNodeHash"]), 653 ) 654 655 @staticmethod 656 def _deserialize_currencies( 657 payload: typedefs.JSONObject, 658 ) -> collections.Sequence[items.Currency]: 659 return [ 660 items.Currency(hash=int(item_hash), amount=int(amount)) 661 for item_hash, amount in payload["itemQuantities"].items() 662 ] 663 664 def deserialize_progressions( 665 self, payload: typedefs.JSONObject 666 ) -> progressions.Progression: 667 return progressions.Progression( 668 hash=int(payload["progressionHash"]), 669 level=int(payload["level"]), 670 cap=int(payload["levelCap"]), 671 daily_limit=int(payload["dailyLimit"]), 672 weekly_limit=int(payload["weeklyLimit"]), 673 current_progress=int(payload["currentProgress"]), 674 daily_progress=int(payload["dailyProgress"]), 675 needed=int(payload["progressToNextLevel"]), 676 next_level=int(payload["nextLevelAt"]), 677 ) 678 679 def _deserialize_factions( 680 self, payload: typedefs.JSONObject 681 ) -> progressions.Factions: 682 progs = self.deserialize_progressions(payload) 683 return progressions.Factions( 684 hash=progs.hash, 685 level=progs.level, 686 cap=progs.cap, 687 daily_limit=progs.daily_limit, 688 weekly_limit=progs.weekly_limit, 689 current_progress=progs.current_progress, 690 daily_progress=progs.daily_progress, 691 needed=progs.needed, 692 next_level=progs.next_level, 693 faction_hash=payload["factionHash"], 694 faction_vendor_hash=payload["factionVendorIndex"], 695 ) 696 697 def _deserialize_milestone_available_quest( 698 self, payload: typedefs.JSONObject 699 ) -> milestones.MilestoneQuest: 700 return milestones.MilestoneQuest( 701 item_hash=payload["questItemHash"], 702 status=self._deserialize_milestone_quest_status(payload["status"]), 703 ) 704 705 def _deserialize_milestone_activity( 706 self, payload: typedefs.JSONObject 707 ) -> milestones.MilestoneActivity: 708 phases: typing.Optional[ 709 collections.Sequence[milestones.MilestoneActivityPhase] 710 ] = None 711 if raw_phases := payload.get("phases"): 712 phases = [ 713 milestones.MilestoneActivityPhase( 714 is_completed=obj["complete"], hash=obj["phaseHash"] 715 ) 716 for obj in raw_phases 717 ] 718 719 return milestones.MilestoneActivity( 720 hash=payload["activityHash"], 721 challenges=[ 722 self.deserialize_objectives(obj["objective"]) 723 for obj in payload["challenges"] 724 ], 725 modifier_hashes=payload.get("modifierHashes"), 726 boolean_options=payload.get("booleanActivityOptions"), 727 phases=phases, 728 ) 729 730 def _deserialize_milestone_quest_status( 731 self, payload: typedefs.JSONObject 732 ) -> milestones.QuestStatus: 733 return milestones.QuestStatus( 734 net=self._net, 735 quest_hash=payload["questHash"], 736 step_hash=payload["stepHash"], 737 step_objectives=[ 738 self.deserialize_objectives(objective) 739 for objective in payload["stepObjectives"] 740 ], 741 is_tracked=payload["tracked"], 742 is_completed=payload["completed"], 743 started=payload["started"], 744 item_instance_id=payload["itemInstanceId"], 745 vendor_hash=payload.get("vendorHash"), 746 is_redeemed=payload["redeemed"], 747 ) 748 749 def _deserialize_milestone_rewards( 750 self, payload: typedefs.JSONObject 751 ) -> milestones.MilestoneReward: 752 return milestones.MilestoneReward( 753 category_hash=payload["rewardCategoryHash"], 754 entries=[ 755 milestones.MilestoneRewardEntry( 756 entry_hash=entry["rewardEntryHash"], 757 is_earned=entry["earned"], 758 is_redeemed=entry["redeemed"], 759 ) 760 for entry in payload["entries"] 761 ], 762 ) 763 764 def deserialize_milestone( 765 self, payload: typedefs.JSONObject 766 ) -> milestones.Milestone: 767 start_date: typing.Optional[datetime.datetime] = None 768 if raw_start_date := payload.get("startDate"): 769 start_date = time.clean_date(raw_start_date) 770 771 end_date: typing.Optional[datetime.datetime] = None 772 if raw_end_date := payload.get("endDate"): 773 end_date = time.clean_date(raw_end_date) 774 775 rewards: typing.Optional[ 776 collections.Collection[milestones.MilestoneReward] 777 ] = None 778 if raw_rewards := payload.get("rewards"): 779 rewards = [ 780 self._deserialize_milestone_rewards(reward) for reward in raw_rewards 781 ] 782 783 activities: typing.Optional[ 784 collections.Sequence[milestones.MilestoneActivity] 785 ] = None 786 if raw_activities := payload.get("activities"): 787 activities = [ 788 self._deserialize_milestone_activity(active) 789 for active in raw_activities 790 ] 791 792 quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None 793 if raw_quests := payload.get("availableQuests"): 794 quests = [ 795 self._deserialize_milestone_available_quest(quest) 796 for quest in raw_quests 797 ] 798 799 vendors: typing.Optional[ 800 collections.Sequence[milestones.MilestoneVendor] 801 ] = None 802 if raw_vendors := payload.get("vendors"): 803 vendors = [ 804 milestones.MilestoneVendor( 805 vendor_hash=vendor["vendorHash"], 806 preview_itemhash=vendor.get("previewItemHash"), 807 ) 808 for vendor in raw_vendors 809 ] 810 811 return milestones.Milestone( 812 hash=payload["milestoneHash"], 813 start_date=start_date, 814 end_date=end_date, 815 order=payload["order"], 816 rewards=rewards, 817 available_quests=quests, 818 activities=activities, 819 vendors=vendors, 820 ) 821 822 def _deserialize_artifact_tiers( 823 self, payload: typedefs.JSONObject 824 ) -> season.ArtifactTier: 825 return season.ArtifactTier( 826 hash=payload["tierHash"], 827 is_unlocked=payload["isUnlocked"], 828 points_to_unlock=payload["pointsToUnlock"], 829 items=[ 830 season.ArtifactTierItem( 831 hash=item["itemHash"], is_active=item["isActive"] 832 ) 833 for item in payload["items"] 834 ], 835 ) 836 837 def deserialize_characters( 838 self, payload: typedefs.JSONObject 839 ) -> collections.Mapping[int, character.Character]: 840 return { 841 int(char_id): self._set_character_attrs(char) 842 for char_id, char in payload["data"].items() 843 } 844 845 def deserialize_character( 846 self, payload: typedefs.JSONObject 847 ) -> character.Character: 848 return self._set_character_attrs(payload) 849 850 def deserialize_character_equipments( 851 self, payload: typedefs.JSONObject 852 ) -> collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]]: 853 return { 854 int(char_id): self.deserialize_profile_items(item) 855 for char_id, item in payload["data"].items() 856 } 857 858 def deserialize_character_activities( 859 self, payload: typedefs.JSONObject 860 ) -> collections.Mapping[int, activity.CharacterActivity]: 861 return { 862 int(char_id): self.deserialize_character_activity(data) 863 for char_id, data in payload["data"].items() 864 } 865 866 def deserialize_characters_render_data( 867 self, payload: typedefs.JSONObject 868 ) -> collections.Mapping[int, character.RenderedData]: 869 return { 870 int(char_id): self.deserialize_character_render_data(data) 871 for char_id, data in payload["data"].items() 872 } 873 874 def deserialize_character_progressions( 875 self, payload: typedefs.JSONObject 876 ) -> character.CharacterProgression: 877 progressions_ = { 878 int(prog_id): self.deserialize_progressions(prog) 879 for prog_id, prog in payload["progressions"].items() 880 } 881 882 factions = { 883 int(faction_id): self._deserialize_factions(faction) 884 for faction_id, faction in payload["factions"].items() 885 } 886 887 milestones_ = { 888 int(milestone_hash): self.deserialize_milestone(milestone) 889 for milestone_hash, milestone in payload["milestones"].items() 890 } 891 892 uninstanced_item_objectives = { 893 int(item_hash): [self.deserialize_objectives(ins) for ins in obj] 894 for item_hash, obj in payload["uninstancedItemObjectives"].items() 895 } 896 897 artifact = payload["seasonalArtifact"] 898 seasonal_artifact = season.CharacterScopedArtifact( 899 hash=artifact["artifactHash"], 900 points_used=artifact["pointsUsed"], 901 reset_count=artifact["resetCount"], 902 tiers=[ 903 self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"] 904 ], 905 ) 906 checklists = payload["checklists"] 907 908 return character.CharacterProgression( 909 progressions=progressions_, 910 factions=factions, 911 checklists=checklists, 912 milestones=milestones_, 913 seasonal_artifact=seasonal_artifact, 914 uninstanced_item_objectives=uninstanced_item_objectives, 915 ) 916 917 def deserialize_character_progressions_mapping( 918 self, payload: typedefs.JSONObject 919 ) -> collections.Mapping[int, character.CharacterProgression]: 920 character_progressions: collections.Mapping[ 921 int, character.CharacterProgression 922 ] = {} 923 for char_id, data in payload["data"].items(): 924 # A little hack to stop mypy complaining about Mapping <-> dict 925 character_progressions[int(char_id)] = self.deserialize_character_progressions(data) # type: ignore[index] 926 return character_progressions 927 928 def deserialize_characters_records( 929 self, 930 payload: typedefs.JSONObject, 931 ) -> collections.Mapping[int, records.CharacterRecord]: 932 return { 933 int(rec_id): self.deserialize_character_records( 934 rec, record_hashes=payload.get("featuredRecordHashes") 935 ) 936 for rec_id, rec in payload["records"].items() 937 } 938 939 def deserialize_profile_records( 940 self, payload: typedefs.JSONObject 941 ) -> collections.Mapping[int, records.Record]: 942 raw_profile_records = payload["data"] 943 scores = records.RecordScores( 944 current_score=raw_profile_records["score"], 945 legacy_score=raw_profile_records["legacyScore"], 946 lifetime_score=raw_profile_records["lifetimeScore"], 947 ) 948 return { 949 int(record_id): self.deserialize_records( 950 record, 951 scores, 952 categories_hash=raw_profile_records["recordCategoriesRootNodeHash"], 953 seals_hash=raw_profile_records["recordSealsRootNodeHash"], 954 ) 955 for record_id, record in raw_profile_records["records"].items() 956 } 957 958 def _deserialize_craftable_socket_plug( 959 self, payload: typedefs.JSONObject 960 ) -> items.CraftableSocketPlug: 961 return items.CraftableSocketPlug( 962 item_hash=int(payload["plugItemHash"]), 963 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), 964 ) 965 966 def _deserialize_craftable_socket( 967 self, payload: typedefs.JSONObject 968 ) -> items.CraftableSocket: 969 plugs: list[items.CraftableSocketPlug] = [] 970 if raw_plug := payload.get("plug"): 971 plugs.extend( 972 self._deserialize_craftable_socket_plug(plug) for plug in raw_plug 973 ) 974 975 return items.CraftableSocket( 976 plug_set_hash=int(payload["plugSetHash"]), plugs=plugs 977 ) 978 979 def _deserialize_craftable_item( 980 self, payload: typedefs.JSONObject 981 ) -> items.CraftableItem: 982 return items.CraftableItem( 983 is_visible=payload["visible"], 984 failed_requirement_indexes=payload.get("failedRequirementIndexes", []), 985 sockets=[ 986 self._deserialize_craftable_socket(socket) 987 for socket in payload["sockets"] 988 ], 989 ) 990 991 def deserialize_craftables_component( 992 self, payload: typedefs.JSONObject 993 ) -> components.CraftablesComponent: 994 return components.CraftablesComponent( 995 net=self._net, 996 craftables={ 997 int(item_id): self._deserialize_craftable_item(item) 998 for item_id, item in payload["craftables"].items() 999 if item is not None 1000 }, 1001 crafting_root_node_hash=payload["craftingRootNodeHash"], 1002 ) 1003 1004 def deserialize_components( # noqa: C901 Too complex. 1005 self, payload: typedefs.JSONObject 1006 ) -> components.Component: 1007 profile_: typing.Optional[profile.Profile] = None 1008 if raw_profile := payload.get("profile"): 1009 profile_ = self.deserialize_profile(raw_profile) 1010 1011 profile_progression: typing.Optional[profile.ProfileProgression] = None 1012 if raw_profile_progression := payload.get("profileProgression"): 1013 profile_progression = self.deserialize_profile_progression( 1014 raw_profile_progression 1015 ) 1016 1017 profile_currencies: typing.Optional[ 1018 collections.Sequence[profile.ProfileItemImpl] 1019 ] = None 1020 if raw_profile_currencies := payload.get("profileCurrencies"): 1021 if "data" in raw_profile_currencies: 1022 profile_currencies = self.deserialize_profile_items( 1023 raw_profile_currencies["data"] 1024 ) 1025 1026 profile_inventories: typing.Optional[ 1027 collections.Sequence[profile.ProfileItemImpl] 1028 ] = None 1029 if raw_profile_inventories := payload.get("profileInventory"): 1030 if "data" in raw_profile_inventories: 1031 profile_inventories = self.deserialize_profile_items( 1032 raw_profile_inventories["data"] 1033 ) 1034 1035 profile_records: typing.Optional[ 1036 collections.Mapping[int, records.Record] 1037 ] = None 1038 1039 if raw_profile_records_ := payload.get("profileRecords"): 1040 profile_records = self.deserialize_profile_records(raw_profile_records_) 1041 1042 characters: typing.Optional[typing.Mapping[int, character.Character]] = None 1043 if raw_characters := payload.get("characters"): 1044 characters = self.deserialize_characters(raw_characters) 1045 1046 character_records: typing.Optional[ 1047 collections.Mapping[int, records.CharacterRecord] 1048 ] = None 1049 1050 if raw_character_records := payload.get("characterRecords"): 1051 # Had to do it in two steps.. 1052 to_update: typedefs.JSONObject = {} 1053 for _, data in raw_character_records["data"].items(): 1054 for record_id, record in data.items(): 1055 to_update[record_id] = record 1056 1057 character_records = { 1058 int(rec_id): self.deserialize_character_records( 1059 rec, record_hashes=to_update.get("featuredRecordHashes") 1060 ) 1061 for rec_id, rec in to_update["records"].items() 1062 } 1063 1064 character_equipments: typing.Optional[ 1065 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] 1066 ] = None 1067 if raw_character_equips := payload.get("characterEquipment"): 1068 character_equipments = self.deserialize_character_equipments( 1069 raw_character_equips 1070 ) 1071 1072 character_inventories: typing.Optional[ 1073 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] 1074 ] = None 1075 if raw_character_inventories := payload.get("characterInventories"): 1076 if "data" in raw_character_inventories: 1077 character_inventories = self.deserialize_character_equipments( 1078 raw_character_inventories 1079 ) 1080 1081 character_activities: typing.Optional[ 1082 collections.Mapping[int, activity.CharacterActivity] 1083 ] = None 1084 if raw_char_acts := payload.get("characterActivities"): 1085 character_activities = self.deserialize_character_activities(raw_char_acts) 1086 1087 character_render_data: typing.Optional[ 1088 collections.Mapping[int, character.RenderedData] 1089 ] = None 1090 if raw_character_render_data := payload.get("characterRenderData"): 1091 character_render_data = self.deserialize_characters_render_data( 1092 raw_character_render_data 1093 ) 1094 1095 character_progressions: typing.Optional[ 1096 collections.Mapping[int, character.CharacterProgression] 1097 ] = None 1098 1099 if raw_character_progressions := payload.get("characterProgressions"): 1100 character_progressions = self.deserialize_character_progressions_mapping( 1101 raw_character_progressions 1102 ) 1103 1104 profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None 1105 if raw_profile_string_vars := payload.get("profileStringVariables"): 1106 profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"] 1107 1108 character_string_vars: typing.Optional[ 1109 collections.Mapping[int, collections.Mapping[int, int]] 1110 ] = None 1111 if raw_character_string_vars := payload.get("characterStringVariables"): 1112 character_string_vars = { 1113 int(char_id): data["integerValuesByHash"] 1114 for char_id, data in raw_character_string_vars["data"].items() 1115 } 1116 1117 metrics: typing.Optional[ 1118 collections.Sequence[ 1119 collections.Mapping[ 1120 int, tuple[bool, typing.Optional[records.Objective]] 1121 ] 1122 ] 1123 ] = None 1124 root_node_hash: typing.Optional[int] = None 1125 1126 if raw_metrics := payload.get("metrics"): 1127 root_node_hash = raw_metrics["data"]["metricsRootNodeHash"] 1128 metrics = [ 1129 { 1130 int(metrics_hash): ( 1131 data["invisible"], 1132 self.deserialize_objectives(data["objectiveProgress"]) 1133 if "objectiveProgress" in data 1134 else None, 1135 ) 1136 for metrics_hash, data in raw_metrics["data"]["metrics"].items() 1137 } 1138 ] 1139 transitory: typing.Optional[fireteams.FireteamParty] = None 1140 if raw_transitory := payload.get("profileTransitoryData"): 1141 if "data" in raw_transitory: 1142 transitory = self.deserialize_fireteam_party(raw_transitory["data"]) 1143 1144 item_components: typing.Optional[components.ItemsComponent] = None 1145 if raw_item_components := payload.get("itemComponents"): 1146 item_components = self.deserialize_items_component(raw_item_components) 1147 1148 profile_plugsets: typing.Optional[ 1149 collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1150 ] = None 1151 1152 if raw_profile_plugs := payload.get("profilePlugSets"): 1153 profile_plugsets = { 1154 int(index): [self.deserialize_plug_item_state(state) for state in data] 1155 for index, data in raw_profile_plugs["data"]["plugs"].items() 1156 } 1157 1158 character_plugsets: typing.Optional[ 1159 collections.Mapping[ 1160 int, collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1161 ] 1162 ] = None 1163 if raw_char_plugsets := payload.get("characterPlugSets"): 1164 character_plugsets = { 1165 int(char_id): { 1166 int(index): [ 1167 self.deserialize_plug_item_state(state) for state in data 1168 ] 1169 for index, data in inner["plugs"].items() 1170 } 1171 for char_id, inner in raw_char_plugsets["data"].items() 1172 } 1173 1174 character_collectibles: typing.Optional[ 1175 collections.Mapping[int, items.Collectible] 1176 ] = None 1177 if raw_character_collectibles := payload.get("characterCollectibles"): 1178 character_collectibles = { 1179 int(char_id): self._deserialize_collectible(data) 1180 for char_id, data in raw_character_collectibles["data"].items() 1181 } 1182 1183 profile_collectibles: typing.Optional[items.Collectible] = None 1184 if raw_profile_collectibles := payload.get("profileCollectibles"): 1185 profile_collectibles = self._deserialize_collectible( 1186 raw_profile_collectibles["data"] 1187 ) 1188 1189 profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None 1190 if raw_profile_nodes := payload.get("profilePresentationNodes"): 1191 profile_nodes = { 1192 int(node_hash): self._deserialize_node(node) 1193 for node_hash, node in raw_profile_nodes["data"]["nodes"].items() 1194 } 1195 1196 character_nodes: typing.Optional[ 1197 collections.Mapping[int, collections.Mapping[int, records.Node]] 1198 ] = None 1199 if raw_character_nodes := payload.get("characterPresentationNodes"): 1200 character_nodes = { 1201 int(char_id): { 1202 int(node_hash): self._deserialize_node(node) 1203 for node_hash, node in each_character["nodes"].items() 1204 } 1205 for char_id, each_character in raw_character_nodes["data"].items() 1206 } 1207 1208 platform_silver: typing.Optional[ 1209 collections.Mapping[str, profile.ProfileItemImpl] 1210 ] = None 1211 if raw_platform_silver := payload.get("platformSilver"): 1212 if "data" in raw_platform_silver: 1213 platform_silver = { 1214 platform_name: self.deserialize_profile_item(item) 1215 for platform_name, item in raw_platform_silver["data"][ 1216 "platformSilver" 1217 ].items() 1218 } 1219 1220 character_currency_lookups: typing.Optional[ 1221 collections.Mapping[int, collections.Sequence[items.Currency]] 1222 ] = None 1223 if raw_char_lookups := payload.get("characterCurrencyLookups"): 1224 if "data" in raw_char_lookups: 1225 character_currency_lookups = { 1226 int(char_id): self._deserialize_currencies(currencie) 1227 for char_id, currencie in raw_char_lookups["data"].items() 1228 } 1229 1230 character_craftables: typing.Optional[ 1231 collections.Mapping[int, components.CraftablesComponent] 1232 ] = None 1233 if raw_character_craftables := payload.get("characterCraftables"): 1234 if "data" in raw_character_craftables: 1235 character_craftables = { 1236 int(char_id): self.deserialize_craftables_component(craftable) 1237 for char_id, craftable in raw_character_craftables["data"].items() 1238 } 1239 1240 return components.Component( 1241 profiles=profile_, 1242 profile_progression=profile_progression, 1243 profile_currencies=profile_currencies, 1244 profile_inventories=profile_inventories, 1245 profile_records=profile_records, 1246 characters=characters, 1247 character_records=character_records, 1248 character_equipments=character_equipments, 1249 character_inventories=character_inventories, 1250 character_activities=character_activities, 1251 character_render_data=character_render_data, 1252 character_progressions=character_progressions, 1253 profile_string_variables=profile_string_vars, 1254 character_string_variables=character_string_vars, 1255 metrics=metrics, 1256 root_node_hash=root_node_hash, 1257 transitory=transitory, 1258 item_components=item_components, 1259 profile_plugsets=profile_plugsets, 1260 character_plugsets=character_plugsets, 1261 character_collectibles=character_collectibles, 1262 profile_collectibles=profile_collectibles, 1263 profile_nodes=profile_nodes, 1264 character_nodes=character_nodes, 1265 platform_silver=platform_silver, 1266 character_currency_lookups=character_currency_lookups, 1267 character_craftables=character_craftables, 1268 ) 1269 1270 def deserialize_items_component( 1271 self, payload: typedefs.JSONObject 1272 ) -> components.ItemsComponent: 1273 instances: typing.Optional[ 1274 collections.Sequence[collections.Mapping[int, items.ItemInstance]] 1275 ] = None 1276 if raw_instances := payload.get("instances"): 1277 instances = [ 1278 { 1279 int(ins_id): self.deserialize_instanced_item(item) 1280 for ins_id, item in raw_instances["data"].items() 1281 } 1282 ] 1283 1284 render_data: typing.Optional[ 1285 collections.Mapping[int, tuple[bool, dict[int, int]]] 1286 ] = None 1287 if raw_render_data := payload.get("renderData"): 1288 render_data = { 1289 int(ins_id): (data["useCustomDyes"], data["artRegions"]) 1290 for ins_id, data in raw_render_data["data"].items() 1291 } 1292 1293 stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None 1294 if raw_stats := payload.get("stats"): 1295 builder: collections.Mapping[int, items.ItemStatsView] = {} 1296 for ins_id, stat in raw_stats["data"].items(): 1297 for _, items_ in stat.items(): 1298 builder[int(ins_id)] = self.deserialize_item_stats_view(items_) # type: ignore[index] 1299 stats = builder 1300 1301 sockets: typing.Optional[ 1302 collections.Mapping[int, collections.Sequence[items.ItemSocket]] 1303 ] = None 1304 if raw_sockets := payload.get("sockets"): 1305 sockets = { 1306 int(ins_id): [ 1307 self.deserialize_item_socket(socket) for socket in item["sockets"] 1308 ] 1309 for ins_id, item in raw_sockets["data"].items() 1310 } 1311 1312 objeectives: typing.Optional[ 1313 collections.Mapping[int, collections.Sequence[records.Objective]] 1314 ] = None 1315 if raw_objectives := payload.get("objectives"): 1316 objeectives = { 1317 int(ins_id): [self.deserialize_objectives(objective)] 1318 for ins_id, data in raw_objectives["data"].items() 1319 for objective in data["objectives"] 1320 } 1321 1322 perks: typing.Optional[ 1323 collections.Mapping[int, collections.Collection[items.ItemPerk]] 1324 ] = None 1325 if raw_perks := payload.get("perks"): 1326 perks = { 1327 int(ins_id): [ 1328 self.deserialize_item_perk(perk) for perk in item["perks"] 1329 ] 1330 for ins_id, item in raw_perks["data"].items() 1331 } 1332 1333 plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None 1334 if raw_plug_states := payload.get("plugStates"): 1335 pending_states: list[items.PlugItemState] = [] 1336 for _, plug in raw_plug_states["data"].items(): 1337 pending_states.append(self.deserialize_plug_item_state(plug)) 1338 plug_states = pending_states 1339 1340 reusable_plugs: typing.Optional[ 1341 collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1342 ] = None 1343 if raw_re_plugs := payload.get("reusablePlugs"): 1344 reusable_plugs = { 1345 int(ins_id): [ 1346 self.deserialize_plug_item_state(state) for state in inner 1347 ] 1348 for ins_id, plug in raw_re_plugs["data"].items() 1349 for inner in list(plug["plugs"].values()) 1350 } 1351 1352 plug_objectives: typing.Optional[ 1353 collections.Mapping[ 1354 int, collections.Mapping[int, collections.Collection[records.Objective]] 1355 ] 1356 ] = None 1357 if raw_plug_objectives := payload.get("plugObjectives"): 1358 plug_objectives = { 1359 int(ins_id): { 1360 int(obj_hash): [self.deserialize_objectives(obj) for obj in objs] 1361 for obj_hash, objs in inner["objectivesPerPlug"].items() 1362 } 1363 for ins_id, inner in raw_plug_objectives["data"].items() 1364 } 1365 1366 return components.ItemsComponent( 1367 sockets=sockets, 1368 stats=stats, 1369 render_data=render_data, 1370 instances=instances, 1371 objectives=objeectives, 1372 perks=perks, 1373 plug_states=plug_states, 1374 reusable_plugs=reusable_plugs, 1375 plug_objectives=plug_objectives, 1376 ) 1377 1378 def deserialize_character_component( # type: ignore[call-arg] 1379 self, payload: typedefs.JSONObject 1380 ) -> components.CharacterComponent: 1381 character_: typing.Optional[character.Character] = None 1382 if raw_singuler_character := payload.get("character"): 1383 character_ = self.deserialize_character(raw_singuler_character["data"]) 1384 1385 inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None 1386 if raw_inventory := payload.get("inventory"): 1387 if "data" in raw_inventory: 1388 inventory = self.deserialize_profile_items(raw_inventory["data"]) 1389 1390 activities: typing.Optional[activity.CharacterActivity] = None 1391 if raw_activities := payload.get("activities"): 1392 activities = self.deserialize_character_activity(raw_activities["data"]) 1393 1394 equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None 1395 if raw_equipments := payload.get("equipment"): 1396 equipment = self.deserialize_profile_items(raw_equipments["data"]) 1397 1398 progressions_: typing.Optional[character.CharacterProgression] = None 1399 if raw_progressions := payload.get("progressions"): 1400 progressions_ = self.deserialize_character_progressions( 1401 raw_progressions["data"] 1402 ) 1403 1404 render_data: typing.Optional[character.RenderedData] = None 1405 if raw_render_data := payload.get("renderData"): 1406 render_data = self.deserialize_character_render_data( 1407 raw_render_data["data"] 1408 ) 1409 1410 character_records: typing.Optional[ 1411 collections.Mapping[int, records.CharacterRecord] 1412 ] = None 1413 if raw_char_records := payload.get("records"): 1414 character_records = self.deserialize_characters_records( 1415 raw_char_records["data"] 1416 ) 1417 1418 item_components: typing.Optional[components.ItemsComponent] = None 1419 if raw_item_components := payload.get("itemComponents"): 1420 item_components = self.deserialize_items_component(raw_item_components) 1421 1422 nodes: typing.Optional[collections.Mapping[int, records.Node]] = None 1423 if raw_nodes := payload.get("presentationNodes"): 1424 nodes = { 1425 int(node_hash): self._deserialize_node(node) 1426 for node_hash, node in raw_nodes["data"]["nodes"].items() 1427 } 1428 1429 collectibles: typing.Optional[items.Collectible] = None 1430 if raw_collectibles := payload.get("collectibles"): 1431 collectibles = self._deserialize_collectible(raw_collectibles["data"]) 1432 1433 currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None 1434 if raw_currencies := payload.get("currencyLookups"): 1435 if "data" in raw_currencies: 1436 currency_lookups = self._deserialize_currencies(raw_currencies) 1437 1438 return components.CharacterComponent( 1439 activities=activities, 1440 equipment=equipment, 1441 inventory=inventory, 1442 progressions=progressions_, 1443 render_data=render_data, 1444 character=character_, 1445 character_records=character_records, 1446 profile_records=None, 1447 item_components=item_components, 1448 currency_lookups=currency_lookups, 1449 collectibles=collectibles, 1450 nodes=nodes, 1451 ) 1452 1453 def _set_entity_attrs( 1454 self, payload: typedefs.JSONObject, *, key: str = "displayProperties" 1455 ) -> entity.Entity: 1456 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1457 description: undefined.UndefinedOr[str] = undefined.UNDEFINED 1458 1459 if properties := payload[key]: 1460 if (raw_name := properties["name"]) is not typedefs.Unknown: 1461 name = raw_name 1462 1463 if ( 1464 raw_description := properties["description"] 1465 ) and not typedefs.is_unknown(raw_description): 1466 description = raw_description 1467 1468 return entity.Entity( 1469 net=self._net, 1470 hash=payload["hash"], 1471 index=payload["index"], 1472 name=name, 1473 description=description, 1474 has_icon=properties["hasIcon"], 1475 icon=assets.Image(properties["icon"] if "icon" in properties else None), 1476 ) 1477 1478 def deserialize_inventory_results( 1479 self, payload: typedefs.JSONObject 1480 ) -> iterators.Iterator[entity.SearchableEntity]: 1481 suggested_words: list[str] = payload["suggestedWords"] 1482 1483 def _check_unknown(s: str) -> undefined.UndefinedOr[str]: 1484 return s if not typedefs.is_unknown(s) else undefined.UNDEFINED 1485 1486 return iterators.Iterator( 1487 [ 1488 entity.SearchableEntity( 1489 net=self._net, 1490 hash=data["hash"], 1491 entity_type=data["entityType"], 1492 weight=data["weight"], 1493 suggested_words=suggested_words, 1494 name=data["displayProperties"]["name"], 1495 has_icon=data["displayProperties"]["hasIcon"], 1496 description=_check_unknown( 1497 data["displayProperties"]["description"] 1498 ), 1499 icon=assets.Image(data["displayProperties"]["icon"]), 1500 ) 1501 for data in payload["results"]["results"] 1502 ] 1503 ) 1504 1505 def _deserialize_inventory_item_objects( 1506 self, payload: typedefs.JSONObject 1507 ) -> entity.InventoryEntityObjects: 1508 return entity.InventoryEntityObjects( 1509 action=payload.get("action"), 1510 set_data=payload.get("setData"), 1511 stats=payload.get("stats"), 1512 equipping_block=payload.get("equippingBlock"), 1513 translation_block=payload.get("translationBlock"), 1514 preview=payload.get("preview"), 1515 quality=payload.get("quality"), 1516 value=payload.get("value"), 1517 source_data=payload.get("sourceData"), 1518 objectives=payload.get("objectives"), 1519 plug=payload.get("plug"), 1520 metrics=payload.get("metrics"), 1521 gearset=payload.get("gearset"), 1522 sack=payload.get("sack"), 1523 sockets=payload.get("sockets"), 1524 summary=payload.get("summary"), 1525 talent_gird=payload.get("talentGrid"), 1526 investments_stats=payload.get("investmentStats"), 1527 perks=payload.get("perks"), 1528 animations=payload.get("animations", []), 1529 links=payload.get("links", []), 1530 ) 1531 1532 def deserialize_inventory_entity( # noqa: C901 Too complex. 1533 self, payload: typedefs.JSONObject, / 1534 ) -> entity.InventoryEntity: 1535 props = self._set_entity_attrs(payload) 1536 objects = self._deserialize_inventory_item_objects(payload) 1537 1538 collectible_hash: typing.Optional[int] = None 1539 if raw_collectible_hash := payload.get("collectibleHash"): 1540 collectible_hash = int(raw_collectible_hash) 1541 1542 secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1543 if raw_second_icon := payload.get("secondaryIcon"): 1544 secondary_icon = assets.Image(raw_second_icon) 1545 1546 secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1547 if raw_second_overlay := payload.get("secondaryOverlay"): 1548 secondary_overlay = assets.Image(raw_second_overlay) 1549 1550 secondary_special: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1551 if raw_second_special := payload.get("secondarySpecial"): 1552 secondary_special = assets.Image(raw_second_special) 1553 1554 screenshot: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1555 if raw_screenshot := payload.get("screenshot"): 1556 screenshot = assets.Image(raw_screenshot) 1557 1558 watermark_icon: typing.Optional[assets.Image] = None 1559 if raw_watermark_icon := payload.get("iconWatermark"): 1560 watermark_icon = assets.Image(raw_watermark_icon) 1561 1562 watermark_shelved: typing.Optional[assets.Image] = None 1563 if raw_watermark_shelved := payload.get("iconWatermarkShelved"): 1564 watermark_shelved = assets.Image(raw_watermark_shelved) 1565 1566 about: undefined.UndefinedOr[str] = undefined.UNDEFINED 1567 if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown( 1568 raw_about 1569 ): 1570 about = raw_about 1571 1572 ui_item_style: undefined.UndefinedOr[str] = undefined.UNDEFINED 1573 if ( 1574 raw_ui_style := payload.get("uiItemDisplayStyle") 1575 ) and not typedefs.is_unknown(raw_ui_style): 1576 ui_item_style = raw_ui_style 1577 1578 tier_and_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1579 if ( 1580 raw_tier_and_name := payload.get("itemTypeAndTierDisplayName") 1581 ) and not typedefs.is_unknown(raw_tier_and_name): 1582 tier_and_name = raw_tier_and_name 1583 1584 type_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1585 if ( 1586 raw_type_name := payload.get("itemTypeDisplayName") 1587 ) and not typedefs.is_unknown(raw_type_name): 1588 type_name = raw_type_name 1589 1590 display_source: undefined.UndefinedOr[str] = undefined.UNDEFINED 1591 if ( 1592 raw_display_source := payload.get("displaySource") 1593 ) and not typedefs.is_unknown(raw_display_source): 1594 display_source = raw_display_source 1595 1596 lorehash: typing.Optional[int] = None 1597 if raw_lore_hash := payload.get("loreHash"): 1598 lorehash = int(raw_lore_hash) 1599 1600 summary_hash: typing.Optional[int] = None 1601 if raw_summary_hash := payload.get("summaryItemHash"): 1602 summary_hash = raw_summary_hash 1603 1604 breaker_type_hash: typing.Optional[int] = None 1605 if raw_breaker_type_hash := payload.get("breakerTypeHash"): 1606 breaker_type_hash = int(raw_breaker_type_hash) 1607 1608 damage_types: typing.Optional[collections.Sequence[int]] = None 1609 if raw_damage_types := payload.get("damageTypes"): 1610 damage_types = [int(type_) for type_ in raw_damage_types] 1611 1612 damagetype_hashes: typing.Optional[collections.Sequence[int]] = None 1613 if raw_damagetype_hashes := payload.get("damageTypeHashes"): 1614 damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes] 1615 1616 default_damagetype_hash: typing.Optional[int] = None 1617 if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"): 1618 default_damagetype_hash = int(raw_defaultdmg_hash) 1619 1620 emblem_objective_hash: typing.Optional[int] = None 1621 if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"): 1622 emblem_objective_hash = int(raw_emblem_obj_hash) 1623 1624 tier_type: typing.Optional[enums.TierType] = None 1625 tier: typing.Optional[enums.ItemTier] = None 1626 bucket_hash: typing.Optional[int] = None 1627 recovery_hash: typing.Optional[int] = None 1628 tier_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1629 isinstance_item: bool = False 1630 expire_tool_tip: undefined.UndefinedOr[str] = undefined.UNDEFINED 1631 expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.UNDEFINED 1632 suppress_expiration: bool = False 1633 max_stack_size: typing.Optional[int] = None 1634 stack_label: undefined.UndefinedOr[str] = undefined.UNDEFINED 1635 1636 if inventory := payload.get("inventory"): 1637 tier_type = enums.TierType(int(inventory["tierType"])) 1638 tier = enums.ItemTier(int(inventory["tierTypeHash"])) 1639 bucket_hash = int(inventory["bucketTypeHash"]) 1640 recovery_hash = int(inventory["recoveryBucketTypeHash"]) 1641 tier_name = inventory["tierTypeName"] 1642 isinstance_item = inventory["isInstanceItem"] 1643 suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"] 1644 max_stack_size = int(inventory["maxStackSize"]) 1645 1646 try: 1647 stack_label = inventory["stackUniqueLabel"] 1648 except KeyError: 1649 pass 1650 1651 return entity.InventoryEntity( 1652 net=self._net, 1653 collectible_hash=collectible_hash, 1654 name=props.name, 1655 about=about, 1656 emblem_objective_hash=emblem_objective_hash, 1657 suppress_expiration=suppress_expiration, 1658 max_stack_size=max_stack_size, 1659 stack_label=stack_label, 1660 tier=tier, 1661 tier_type=tier_type, 1662 tier_name=tier_name, 1663 bucket_hash=bucket_hash, 1664 recovery_bucket_hash=recovery_hash, 1665 isinstance_item=isinstance_item, 1666 expire_in_orbit_message=expire_in_orbit_message, 1667 expiration_tooltip=expire_tool_tip, 1668 lore_hash=lorehash, 1669 type_and_tier_name=tier_and_name, 1670 summary_hash=summary_hash, 1671 ui_display_style=ui_item_style, 1672 type_name=type_name, 1673 breaker_type_hash=breaker_type_hash, 1674 description=props.description, 1675 display_source=display_source, 1676 hash=props.hash, 1677 damage_types=damage_types, 1678 index=props.index, 1679 icon=props.icon, 1680 has_icon=props.has_icon, 1681 screenshot=screenshot, 1682 watermark_icon=watermark_icon, 1683 watermark_shelved=watermark_shelved, 1684 secondary_icon=secondary_icon, 1685 secondary_overlay=secondary_overlay, 1686 secondary_special=secondary_special, 1687 type=enums.ItemType(int(payload["itemType"])), 1688 trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])], 1689 trait_ids=[trait for trait in payload.get("traitIds", [])], 1690 category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]], 1691 item_class=enums.Class(int(payload["classType"])), 1692 sub_type=enums.ItemSubType(int(payload["itemSubType"])), 1693 breaker_type=int(payload["breakerType"]), 1694 default_damagetype=int(payload["defaultDamageType"]), 1695 default_damagetype_hash=default_damagetype_hash, 1696 damagetype_hashes=damagetype_hashes, 1697 tooltip_notifications=payload["tooltipNotifications"], 1698 not_transferable=payload["nonTransferrable"], 1699 allow_actions=payload["allowActions"], 1700 is_equippable=payload["equippable"], 1701 objects=objects, 1702 background_colors=payload.get("backgroundColor", {}), 1703 season_hash=payload.get("seasonHash"), 1704 has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"], 1705 ) 1706 1707 def deserialize_objective_entity( 1708 self, payload: typedefs.JSONObject, / 1709 ) -> entity.ObjectiveEntity: 1710 props = self._set_entity_attrs(payload) 1711 return entity.ObjectiveEntity( 1712 net=self._net, 1713 hash=props.hash, 1714 index=props.index, 1715 description=props.description, 1716 name=props.name, 1717 has_icon=props.has_icon, 1718 icon=props.icon, 1719 unlock_value_hash=payload["unlockValueHash"], 1720 completion_value=payload["completionValue"], 1721 scope=entity.GatingScope(int(payload["scope"])), 1722 location_hash=payload["locationHash"], 1723 allowed_negative_value=payload["allowNegativeValue"], 1724 allowed_value_change=payload["allowValueChangeWhenCompleted"], 1725 counting_downward=payload["isCountingDownward"], 1726 value_style=entity.ValueUIStyle(int(payload["valueStyle"])), 1727 progress_description=payload["progressDescription"], 1728 perks=payload["perks"], 1729 stats=payload["stats"], 1730 minimum_visibility=payload["minimumVisibilityThreshold"], 1731 allow_over_completion=payload["allowOvercompletion"], 1732 show_value_style=payload["showValueOnComplete"], 1733 display_only_objective=payload["isDisplayOnlyObjective"], 1734 complete_value_style=entity.ValueUIStyle( 1735 int(payload["completedValueStyle"]) 1736 ), 1737 progress_value_style=entity.ValueUIStyle( 1738 int(payload["inProgressValueStyle"]) 1739 ), 1740 ui_label=payload["uiLabel"], 1741 ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])), 1742 ) 1743 1744 def _deserialize_activity_values( 1745 self, payload: typedefs.JSONObject, / 1746 ) -> activity.ActivityValues: 1747 team: typing.Optional[int] = None 1748 if raw_team := payload.get("team"): 1749 team = raw_team["basic"]["value"] 1750 return activity.ActivityValues( 1751 assists=payload["assists"]["basic"]["value"], 1752 deaths=payload["deaths"]["basic"]["value"], 1753 kills=payload["kills"]["basic"]["value"], 1754 is_completed=bool(payload["completed"]["basic"]["value"]), 1755 opponents_defeated=payload["opponentsDefeated"]["basic"]["value"], 1756 efficiency=payload["efficiency"]["basic"]["value"], 1757 kd_ratio=payload["killsDeathsRatio"]["basic"]["value"], 1758 kd_assists=payload["killsDeathsAssists"]["basic"]["value"], 1759 score=payload["score"]["basic"]["value"], 1760 duration=payload["activityDurationSeconds"]["basic"]["displayValue"], 1761 team=team, 1762 completion_reason=payload["completionReason"]["basic"]["displayValue"], 1763 fireteam_id=payload["fireteamId"]["basic"]["value"], 1764 start_seconds=payload["startSeconds"]["basic"]["value"], 1765 played_time=payload["timePlayedSeconds"]["basic"]["displayValue"], 1766 player_count=payload["playerCount"]["basic"]["value"], 1767 team_score=payload["teamScore"]["basic"]["value"], 1768 ) 1769 1770 def deserialize_activity( 1771 self, 1772 payload: typedefs.JSONObject, 1773 /, 1774 ) -> activity.Activity: 1775 period = time.clean_date(payload["period"]) 1776 details = payload["activityDetails"] 1777 ref_id = int(details["referenceId"]) 1778 instance_id = int(details["instanceId"]) 1779 mode = enums.GameMode(details["mode"]) 1780 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] 1781 is_private = details["isPrivate"] 1782 membership_type = enums.MembershipType(int(details["membershipType"])) 1783 1784 # Since we're using the same fields for post activity method 1785 # this check is required since post activity doesn't values values 1786 values = self._deserialize_activity_values(payload["values"]) 1787 1788 return activity.Activity( 1789 net=self._net, 1790 hash=ref_id, 1791 instance_id=instance_id, 1792 mode=mode, 1793 modes=modes, 1794 is_private=is_private, 1795 membership_type=membership_type, 1796 occurred_at=period, 1797 values=values, 1798 ) 1799 1800 def deserialize_activities( 1801 self, payload: typedefs.JSONObject 1802 ) -> iterators.Iterator[activity.Activity]: 1803 return iterators.Iterator( 1804 [ 1805 self.deserialize_activity(activity_) 1806 for activity_ in payload["activities"] 1807 ] 1808 ) 1809 1810 def deserialize_extended_weapon_values( 1811 self, payload: typedefs.JSONObject 1812 ) -> activity.ExtendedWeaponValues: 1813 assists: typing.Optional[int] = None 1814 if raw_assists := payload["values"].get("uniqueWeaponAssists"): 1815 assists = raw_assists["basic"]["value"] 1816 assists_damage: typing.Optional[int] = None 1817 1818 if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"): 1819 assists_damage = raw_assists_damage["basic"]["value"] 1820 1821 return activity.ExtendedWeaponValues( 1822 reference_id=int(payload["referenceId"]), 1823 kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"], 1824 precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][ 1825 "value" 1826 ], 1827 assists=assists, 1828 assists_damage=assists_damage, 1829 precision_kills_percentage=( 1830 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"], 1831 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][ 1832 "displayValue" 1833 ], 1834 ), 1835 ) 1836 1837 def _deserialize_extended_values( 1838 self, payload: typedefs.JSONObject 1839 ) -> activity.ExtendedValues: 1840 weapons: typing.Optional[ 1841 collections.Collection[activity.ExtendedWeaponValues] 1842 ] = None 1843 1844 if raw_weapons := payload.get("weapons"): 1845 weapons = [ 1846 self.deserialize_extended_weapon_values(value) for value in raw_weapons 1847 ] 1848 1849 return activity.ExtendedValues( 1850 precision_kills=payload["values"]["precisionKills"]["basic"]["value"], 1851 grenade_kills=payload["values"]["weaponKillsGrenade"]["basic"]["value"], 1852 melee_kills=payload["values"]["weaponKillsMelee"]["basic"]["value"], 1853 super_kills=payload["values"]["weaponKillsSuper"]["basic"]["value"], 1854 ability_kills=payload["values"]["weaponKillsAbility"]["basic"]["value"], 1855 weapons=weapons, 1856 ) 1857 1858 def deserialize_post_activity_player( 1859 self, payload: typedefs.JSONObject, / 1860 ) -> activity.PostActivityPlayer: 1861 player = payload["player"] 1862 1863 class_hash: typedefs.NoneOr[int] = None 1864 if (class_hash := player.get("classHash")) is not None: 1865 class_hash = class_hash 1866 1867 race_hash: typedefs.NoneOr[int] = None 1868 if (race_hash := player.get("raceHash")) is not None: 1869 race_hash = race_hash 1870 1871 gender_hash: typedefs.NoneOr[int] = None 1872 if (gender_hash := player.get("genderHash")) is not None: 1873 gender_hash = gender_hash 1874 1875 character_class: undefined.UndefinedOr[str] = undefined.UNDEFINED 1876 if ( 1877 character_class := player.get("characterClass") 1878 ) and not typedefs.is_unknown(character_class): 1879 character_class = character_class 1880 1881 character_level: typedefs.NoneOr[int] = None 1882 if (character_level := player.get("characterLevel")) is not None: 1883 character_level = character_level 1884 1885 return activity.PostActivityPlayer( 1886 standing=int(payload["standing"]), 1887 score=int(payload["score"]["basic"]["value"]), 1888 character_id=payload["characterId"], 1889 destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]), 1890 character_class=character_class, 1891 character_level=character_level, 1892 race_hash=race_hash, 1893 gender_hash=gender_hash, 1894 class_hash=class_hash, 1895 light_level=int(player["lightLevel"]), 1896 emblem_hash=int(player["emblemHash"]), 1897 values=self._deserialize_activity_values(payload["values"]), 1898 extended_values=self._deserialize_extended_values(payload["extended"]), 1899 ) 1900 1901 def _deserialize_post_activity_team( 1902 self, payload: typedefs.JSONObject 1903 ) -> activity.PostActivityTeam: 1904 return activity.PostActivityTeam( 1905 id=payload["teamId"], 1906 is_defeated=bool(payload["standing"]["basic"]["value"]), 1907 score=int(payload["score"]["basic"]["value"]), 1908 name=payload["teamName"], 1909 ) 1910 1911 def deserialize_post_activity( 1912 self, payload: typedefs.JSONObject 1913 ) -> activity.PostActivity: 1914 period = time.clean_date(payload["period"]) 1915 details = payload["activityDetails"] 1916 ref_id = int(details["referenceId"]) 1917 instance_id = int(details["instanceId"]) 1918 mode = enums.GameMode(details["mode"]) 1919 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] 1920 is_private = details["isPrivate"] 1921 membership_type = enums.MembershipType(int(details["membershipType"])) 1922 return activity.PostActivity( 1923 net=self._net, 1924 hash=ref_id, 1925 membership_type=membership_type, 1926 instance_id=instance_id, 1927 mode=mode, 1928 modes=modes, 1929 is_private=is_private, 1930 occurred_at=period, 1931 starting_phase=int(payload["startingPhaseIndex"]), 1932 players=[ 1933 self.deserialize_post_activity_player(player) 1934 for player in payload["entries"] 1935 ], 1936 teams=[ 1937 self._deserialize_post_activity_team(team) for team in payload["teams"] 1938 ], 1939 ) 1940 1941 def _deserialize_aggregated_activity_values( 1942 self, payload: typedefs.JSONObject 1943 ) -> activity.AggregatedActivityValues: 1944 # This ID is always the same for all aggregated values. 1945 activity_id = int(payload["fastestCompletionMsForActivity"]["activityId"]) 1946 1947 return activity.AggregatedActivityValues( 1948 id=activity_id, 1949 fastest_completion_time=( 1950 int(payload["fastestCompletionMsForActivity"]["basic"]["value"]), 1951 payload["fastestCompletionMsForActivity"]["basic"]["displayValue"], 1952 ), 1953 completions=int(payload["activityCompletions"]["basic"]["value"]), 1954 kills=int(payload["activityKills"]["basic"]["value"]), 1955 deaths=int(payload["activityDeaths"]["basic"]["value"]), 1956 assists=int(payload["activityAssists"]["basic"]["value"]), 1957 seconds_played=( 1958 int(payload["activitySecondsPlayed"]["basic"]["value"]), 1959 payload["activitySecondsPlayed"]["basic"]["displayValue"], 1960 ), 1961 wins=int(payload["activityWins"]["basic"]["value"]), 1962 goals_missed=int(payload["activityGoalsMissed"]["basic"]["value"]), 1963 special_actions=int(payload["activitySpecialActions"]["basic"]["value"]), 1964 best_goals_hit=int(payload["activityBestGoalsHit"]["basic"]["value"]), 1965 best_single_score=int( 1966 payload["activityBestSingleGameScore"]["basic"]["value"] 1967 ), 1968 goals_hit=int(payload["activityGoalsHit"]["basic"]["value"]), 1969 special_score=int(payload["activitySpecialScore"]["basic"]["value"]), 1970 kd_assists=int(payload["activityKillsDeathsAssists"]["basic"]["value"]), 1971 kd_ratio=float( 1972 payload["activityKillsDeathsAssists"]["basic"]["displayValue"] 1973 ), 1974 precision_kills=int(payload["activityPrecisionKills"]["basic"]["value"]), 1975 ) 1976 1977 def deserialize_aggregated_activity( 1978 self, payload: typedefs.JSONObject 1979 ) -> activity.AggregatedActivity: 1980 return activity.AggregatedActivity( 1981 hash=int(payload["activityHash"]), 1982 values=self._deserialize_aggregated_activity_values(payload["values"]), 1983 ) 1984 1985 def deserialize_aggregated_activities( 1986 self, payload: typedefs.JSONObject 1987 ) -> iterators.Iterator[activity.AggregatedActivity]: 1988 return iterators.Iterator( 1989 [ 1990 self.deserialize_aggregated_activity(activity) 1991 for activity in payload["activities"] 1992 ] 1993 ) 1994 1995 def deserialize_linked_profiles( 1996 self, payload: typedefs.JSONObject 1997 ) -> profile.LinkedProfile: 1998 bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"]) 1999 error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] 2000 profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] 2001 2002 if raw_profile := payload.get("profiles"): 2003 for pfile in raw_profile: 2004 profiles_vec.append(self.deserialize_destiny_membership(pfile)) 2005 2006 if raw_profiles_with_errors := payload.get("profilesWithErrors"): 2007 for raw_error_pfile in raw_profiles_with_errors: 2008 if error_pfile := raw_error_pfile.get("infoCard"): 2009 error_profiles_vec.append( 2010 self.deserialize_destiny_membership(error_pfile) 2011 ) 2012 2013 return profile.LinkedProfile( 2014 net=self._net, 2015 bungie=bungie_user, 2016 profiles=profiles_vec, 2017 profiles_with_errors=error_profiles_vec, 2018 ) 2019 2020 def deserialize_clan_banners( 2021 self, payload: typedefs.JSONObject 2022 ) -> collections.Sequence[clans.ClanBanner]: 2023 banners_seq: typing.MutableSequence[clans.ClanBanner] = [] 2024 if banners := payload.get("clanBannerDecals"): 2025 for k, v in banners.items(): 2026 banner_obj = clans.ClanBanner( 2027 id=int(k), 2028 foreground=assets.Image(v["foregroundPath"]), 2029 background=assets.Image(v["backgroundPath"]), 2030 ) 2031 banners_seq.append(banner_obj) 2032 return banners_seq 2033 2034 def deserialize_public_milestone_content( 2035 self, payload: typedefs.JSONObject 2036 ) -> milestones.MilestoneContent: 2037 items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None 2038 if raw_categories := payload.get("itemCategories"): 2039 for item in raw_categories: 2040 title = undefined.UNDEFINED 2041 if raw_title := item.get("title"): 2042 if raw_title != typedefs.Unknown: 2043 title = raw_title 2044 if raw_hashes := item.get("itemHashes"): 2045 hashes: collections.Sequence[int] = raw_hashes 2046 2047 items_categoris = milestones.MilestoneItems(title=title, hashes=hashes) 2048 2049 about = undefined.UNDEFINED 2050 if (raw_about := payload["about"]) != typedefs.Unknown: 2051 about = raw_about 2052 2053 status = undefined.UNDEFINED 2054 if (raw_status := payload["status"]) != typedefs.Unknown: 2055 status = raw_status 2056 2057 tips: typing.MutableSequence[undefined.UndefinedOr[str]] = [] 2058 if raw_tips := payload.get("tips"): 2059 for raw_tip in raw_tips: 2060 if raw_tip == typedefs.Unknown: 2061 raw_tip = undefined.UNDEFINED 2062 tips.append(raw_tip) 2063 2064 return milestones.MilestoneContent( 2065 about=about, status=status, tips=tips, items=items_categoris 2066 ) 2067 2068 def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend: 2069 name = undefined.UNDEFINED 2070 if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown: 2071 name = raw_name 2072 2073 bungie_user: typedefs.NoneOr[user.BungieUser] = None 2074 2075 if raw_bungie_user := payload.get("bungieNetUser"): 2076 bungie_user = self.deserialize_bungie_user(raw_bungie_user) 2077 2078 return friends.Friend( 2079 net=self._net, 2080 id=int(payload["lastSeenAsMembershipId"]), 2081 name=name, 2082 code=payload.get("bungieGlobalDisplayNameCode"), 2083 relationship=enums.Relationship(payload["relationship"]), 2084 user=bungie_user, 2085 online_status=enums.Presence(payload["onlineStatus"]), 2086 online_title=payload["onlineTitle"], 2087 type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]), 2088 ) 2089 2090 def deserialize_friends( 2091 self, payload: typedefs.JSONObject 2092 ) -> collections.Sequence[friends.Friend]: 2093 mut_seq: typing.MutableSequence[friends.Friend] = [] 2094 if raw_friends := payload.get("friends"): 2095 for friend in raw_friends: 2096 mut_seq.append(self.deserialize_friend(friend)) 2097 return mut_seq 2098 2099 def deserialize_friend_requests( 2100 self, payload: typedefs.JSONObject 2101 ) -> friends.FriendRequestView: 2102 incoming: typing.MutableSequence[friends.Friend] = [] 2103 outgoing: typing.MutableSequence[friends.Friend] = [] 2104 2105 if raw_incoming_requests := payload.get("incomingRequests"): 2106 for incoming_request in raw_incoming_requests: 2107 incoming.append(self.deserialize_friend(incoming_request)) 2108 2109 if raw_outgoing_requests := payload.get("outgoingRequests"): 2110 for outgoing_request in raw_outgoing_requests: 2111 outgoing.append(self.deserialize_friend(outgoing_request)) 2112 2113 return friends.FriendRequestView(incoming=incoming, outgoing=outgoing) 2114 2115 def _set_fireteam_fields( 2116 self, payload: typedefs.JSONObject, total_results: typing.Optional[int] = None 2117 ) -> fireteams.Fireteam: 2118 activity_type = fireteams.FireteamActivity(payload["activityType"]) 2119 return fireteams.Fireteam( 2120 id=int(payload["fireteamId"]), 2121 group_id=int(payload["groupId"]), 2122 platform=fireteams.FireteamPlatform(payload["platform"]), 2123 is_immediate=payload["isImmediate"], 2124 activity_type=activity_type, 2125 owner_id=int(payload["ownerMembershipId"]), 2126 player_slot_count=payload["playerSlotCount"], 2127 available_player_slots=payload["availablePlayerSlotCount"], 2128 available_alternate_slots=payload["availableAlternateSlotCount"], 2129 title=payload["title"], 2130 date_created=time.clean_date(payload["dateCreated"]), 2131 is_public=payload["isPublic"], 2132 locale=fireteams.FireteamLanguage(payload["locale"]), 2133 is_valid=payload["isValid"], 2134 last_modified=time.clean_date(payload["datePlayerModified"]), 2135 total_results=total_results or 0, 2136 ) 2137 2138 def deserialize_fireteams( 2139 self, payload: typedefs.JSONObject 2140 ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]: 2141 fireteams_: typing.MutableSequence[fireteams.Fireteam] = [] 2142 2143 result: list[typedefs.JSONObject] 2144 if not (result := payload["results"]): 2145 return None 2146 for elem in result: 2147 fireteams_.append( 2148 self._set_fireteam_fields( 2149 elem, total_results=int(payload["totalResults"]) 2150 ) 2151 ) 2152 return fireteams_ 2153 2154 def deserialize_fireteam_destiny_users( 2155 self, payload: typedefs.JSONObject 2156 ) -> fireteams.FireteamUser: 2157 destiny_obj = self.deserialize_destiny_membership(payload) 2158 # We could helpers.just return a DestinyMembership object but this is 2159 # missing the fireteam display name and id fields. 2160 return fireteams.FireteamUser( 2161 net=self._net, 2162 id=destiny_obj.id, 2163 code=destiny_obj.code, 2164 icon=destiny_obj.icon, 2165 types=destiny_obj.types, 2166 type=destiny_obj.type, 2167 is_public=destiny_obj.is_public, 2168 crossave_override=destiny_obj.crossave_override, 2169 name=destiny_obj.name, 2170 last_seen_name=destiny_obj.last_seen_name, 2171 fireteam_display_name=payload["FireteamDisplayName"], 2172 fireteam_membership_id=enums.MembershipType( 2173 payload["FireteamMembershipType"] 2174 ), 2175 ) 2176 2177 def deserialize_fireteam_members( 2178 self, payload: typedefs.JSONObject, *, alternatives: bool = False 2179 ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]: 2180 members_: list[fireteams.FireteamMember] = [] 2181 if members := payload.get("Members" if not alternatives else "Alternates"): 2182 for member in members: 2183 bungie_fields = self.deserialize_partial_bungie_user(member) 2184 members_fields = fireteams.FireteamMember( 2185 destiny_user=self.deserialize_fireteam_destiny_users(member), 2186 has_microphone=member["hasMicrophone"], 2187 character_id=int(member["characterId"]), 2188 date_joined=time.clean_date(member["dateJoined"]), 2189 last_platform_invite_date=time.clean_date( 2190 member["lastPlatformInviteAttemptDate"] 2191 ), 2192 last_platform_invite_result=int( 2193 member["lastPlatformInviteAttemptResult"] 2194 ), 2195 net=self._net, 2196 name=bungie_fields.name, 2197 id=bungie_fields.id, 2198 icon=bungie_fields.icon, 2199 is_public=bungie_fields.is_public, 2200 crossave_override=bungie_fields.crossave_override, 2201 types=bungie_fields.types, 2202 type=bungie_fields.type, 2203 ) 2204 members_.append(members_fields) 2205 else: 2206 return None 2207 return members_ 2208 2209 def deserialize_available_fireteams( 2210 self, 2211 data: typedefs.JSONObject, 2212 *, 2213 no_results: bool = False, 2214 ) -> typing.Union[ 2215 fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam] 2216 ]: 2217 fireteams_: list[fireteams.AvailableFireteam] = [] 2218 2219 # This needs to be used outside the results 2220 # JSON key. 2221 if no_results is True: 2222 payload = data 2223 2224 if result := payload.get("results"): 2225 for fireteam in result: 2226 found_fireteams = self._set_fireteam_fields(fireteam["Summary"]) 2227 fireteams_fields = fireteams.AvailableFireteam( 2228 id=found_fireteams.id, 2229 group_id=found_fireteams.group_id, 2230 platform=found_fireteams.platform, 2231 activity_type=found_fireteams.activity_type, 2232 is_immediate=found_fireteams.is_immediate, 2233 is_public=found_fireteams.is_public, 2234 is_valid=found_fireteams.is_valid, 2235 owner_id=found_fireteams.owner_id, 2236 player_slot_count=found_fireteams.player_slot_count, 2237 available_player_slots=found_fireteams.available_player_slots, 2238 available_alternate_slots=found_fireteams.available_alternate_slots, 2239 title=found_fireteams.title, 2240 date_created=found_fireteams.date_created, 2241 locale=found_fireteams.locale, 2242 last_modified=found_fireteams.last_modified, 2243 total_results=found_fireteams.total_results, 2244 members=self.deserialize_fireteam_members(payload), 2245 alternatives=self.deserialize_fireteam_members( 2246 payload, alternatives=True 2247 ), 2248 ) 2249 fireteams_.append(fireteams_fields) 2250 if no_results: 2251 return fireteams_fields 2252 return fireteams_ 2253 2254 def deserialize_fireteam_party( 2255 self, payload: typedefs.JSONObject 2256 ) -> fireteams.FireteamParty: 2257 last_destination_hash: typing.Optional[int] = None 2258 if raw_dest_hash := payload.get("lastOrbitedDestinationHash"): 2259 last_destination_hash = int(raw_dest_hash) 2260 2261 return fireteams.FireteamParty( 2262 members=[ 2263 self._deserialize_fireteam_party_member(member) 2264 for member in payload["partyMembers"] 2265 ], 2266 activity=self._deserialize_fireteam_party_current_activity( 2267 payload["currentActivity"] 2268 ), 2269 settings=self._deserialize_fireteam_party_settings(payload["joinability"]), 2270 last_destination_hash=last_destination_hash, 2271 tracking=payload["tracking"], 2272 ) 2273 2274 def _deserialize_fireteam_party_member( 2275 self, payload: typedefs.JSONObject 2276 ) -> fireteams.FireteamPartyMember: 2277 status = fireteams.FireteamPartyMemberState(payload["status"]) 2278 displayname: undefined.UndefinedOr[str] = undefined.UNDEFINED 2279 if raw_name := payload.get("displayName"): 2280 displayname = raw_name 2281 2282 return fireteams.FireteamPartyMember( 2283 membership_id=int(payload["membershipId"]), 2284 emblem_hash=int(payload["emblemHash"]), 2285 status=status, 2286 display_name=displayname, 2287 ) 2288 2289 def _deserialize_fireteam_party_current_activity( 2290 self, payload: typedefs.JSONObject 2291 ) -> fireteams.FireteamPartyCurrentActivity: 2292 start_date: typing.Optional[datetime.datetime] = None 2293 if raw_start_date := payload.get("startTime"): 2294 start_date = time.clean_date(raw_start_date) 2295 2296 end_date: typing.Optional[datetime.datetime] = None 2297 if raw_end_date := payload.get("endTime"): 2298 end_date = time.clean_date(raw_end_date) 2299 return fireteams.FireteamPartyCurrentActivity( 2300 start_time=start_date, 2301 end_time=end_date, 2302 score=float(payload["score"]), 2303 highest_opposing_score=float(payload["highestOpposingFactionScore"]), 2304 opponenst_count=int(payload["numberOfOpponents"]), 2305 player_count=int(payload["numberOfPlayers"]), 2306 ) 2307 2308 def _deserialize_fireteam_party_settings( 2309 self, payload: typedefs.JSONObject 2310 ) -> fireteams.FireteamPartySettings: 2311 closed_reasons = enums.ClosedReasons(payload["closedReasons"]) 2312 return fireteams.FireteamPartySettings( 2313 open_slots=int(payload["openSlots"]), 2314 privacy_setting=enums.PrivacySetting(int(payload["privacySetting"])), 2315 closed_reasons=closed_reasons, 2316 ) 2317 2318 def deserialize_seasonal_artifact( 2319 self, payload: typedefs.JSONObject 2320 ) -> season.Artifact: 2321 if raw_artifact := payload.get("seasonalArtifact"): 2322 if points := raw_artifact.get("pointProgression"): 2323 points_prog = progressions.Progression( 2324 hash=points["progressionHash"], 2325 level=points["level"], 2326 cap=points["levelCap"], 2327 daily_limit=points["dailyLimit"], 2328 weekly_limit=points["weeklyLimit"], 2329 current_progress=points["currentProgress"], 2330 daily_progress=points["dailyProgress"], 2331 needed=points["progressToNextLevel"], 2332 next_level=points["nextLevelAt"], 2333 ) 2334 2335 if bonus := raw_artifact.get("powerBonusProgression"): 2336 power_bonus_prog = progressions.Progression( 2337 hash=bonus["progressionHash"], 2338 level=bonus["level"], 2339 cap=bonus["levelCap"], 2340 daily_limit=bonus["dailyLimit"], 2341 weekly_limit=bonus["weeklyLimit"], 2342 current_progress=bonus["currentProgress"], 2343 daily_progress=bonus["dailyProgress"], 2344 needed=bonus["progressToNextLevel"], 2345 next_level=bonus["nextLevelAt"], 2346 ) 2347 artifact = season.Artifact( 2348 net=self._net, 2349 hash=raw_artifact["artifactHash"], 2350 power_bonus=raw_artifact["powerBonus"], 2351 acquired_points=raw_artifact["pointsAcquired"], 2352 bonus=power_bonus_prog, 2353 points=points_prog, 2354 ) 2355 return artifact 2356 2357 def deserialize_profile_progression( 2358 self, payload: typedefs.JSONObject 2359 ) -> profile.ProfileProgression: 2360 return profile.ProfileProgression( 2361 artifact=self.deserialize_seasonal_artifact(payload["data"]), 2362 checklist={ 2363 int(check_id): checklists 2364 for check_id, checklists in payload["data"]["checklists"].items() 2365 }, 2366 ) 2367 2368 def deserialize_instanced_item( 2369 self, payload: typedefs.JSONObject 2370 ) -> items.ItemInstance: 2371 damage_type_hash: typing.Optional[int] = None 2372 if raw_damagetype_hash := payload.get("damageTypeHash"): 2373 damage_type_hash = int(raw_damagetype_hash) 2374 2375 required_hashes: typing.Optional[collections.Collection[int]] = None 2376 if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"): 2377 required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes] 2378 2379 breaker_type: typing.Optional[items.ItemBreakerType] = None 2380 if raw_break_type := payload.get("breakerType"): 2381 breaker_type = items.ItemBreakerType(int(raw_break_type)) 2382 2383 breaker_type_hash: typing.Optional[int] = None 2384 if raw_break_type_hash := payload.get("breakerTypeHash"): 2385 breaker_type_hash = int(raw_break_type_hash) 2386 2387 energy: typing.Optional[items.ItemEnergy] = None 2388 if raw_energy := payload.get("energy"): 2389 energy = self.deserialize_item_energy(raw_energy) 2390 2391 primary_stats = None 2392 if raw_primary_stats := payload.get("primaryStat"): 2393 primary_stats = self.deserialize_item_stats_view(raw_primary_stats) 2394 2395 return items.ItemInstance( 2396 damage_type=enums.DamageType(int(payload["damageType"])), 2397 damage_type_hash=damage_type_hash, 2398 primary_stat=primary_stats, 2399 item_level=int(payload["itemLevel"]), 2400 quality=int(payload["quality"]), 2401 is_equipped=payload["isEquipped"], 2402 can_equip=payload["canEquip"], 2403 equip_required_level=int(payload["equipRequiredLevel"]), 2404 required_equip_unlock_hashes=required_hashes, 2405 cant_equip_reason=int(payload["cannotEquipReason"]), 2406 breaker_type=breaker_type, 2407 breaker_type_hash=breaker_type_hash, 2408 energy=energy, 2409 ) 2410 2411 def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy: 2412 energy_hash: typing.Optional[int] = None 2413 if raw_energy_hash := payload.get("energyTypeHash"): 2414 energy_hash = int(raw_energy_hash) 2415 2416 return items.ItemEnergy( 2417 hash=energy_hash, 2418 type=items.ItemEnergyType(int(payload["energyType"])), 2419 capacity=int(payload["energyCapacity"]), 2420 used_energy=int(payload["energyUsed"]), 2421 unused_energy=int(payload["energyUnused"]), 2422 ) 2423 2424 def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk: 2425 perk_hash: typing.Optional[int] = None 2426 if raw_perk_hash := payload.get("perkHash"): 2427 perk_hash = int(raw_perk_hash) 2428 2429 return items.ItemPerk( 2430 hash=perk_hash, 2431 icon=assets.Image(payload["iconPath"]), 2432 is_active=payload["isActive"], 2433 is_visible=payload["visible"], 2434 ) 2435 2436 def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket: 2437 plug_hash: typing.Optional[int] = None 2438 if raw_plug_hash := payload.get("plugHash"): 2439 plug_hash = int(raw_plug_hash) 2440 2441 enable_fail_indexes: typing.Optional[list[int]] = None 2442 if raw_indexes := payload.get("enableFailIndexes"): 2443 enable_fail_indexes = [int(index) for index in raw_indexes] 2444 2445 return items.ItemSocket( 2446 plug_hash=plug_hash, 2447 is_enabled=payload["isEnabled"], 2448 enable_fail_indexes=enable_fail_indexes, 2449 is_visible=payload.get("visible"), 2450 ) 2451 2452 def deserialize_item_stats_view( 2453 self, payload: typedefs.JSONObject 2454 ) -> items.ItemStatsView: 2455 return items.ItemStatsView( 2456 stat_hash=payload.get("statHash"), value=payload.get("value") 2457 ) 2458 2459 def deserialize_plug_item_state( 2460 self, payload: typedefs.JSONObject 2461 ) -> items.PlugItemState: 2462 item_hash: typing.Optional[int] = None 2463 if raw_item_hash := payload.get("plugItemHash"): 2464 item_hash = int(raw_item_hash) 2465 2466 insert_fail_indexes: typedefs.NoneOr[list[int]] = None 2467 if raw_fail_indexes := payload.get("insertFailIndexes"): 2468 insert_fail_indexes = [int(k) for k in raw_fail_indexes] 2469 2470 enable_fail_indexes: typedefs.NoneOr[list[int]] = None 2471 if raw_enabled_indexes := payload.get("enableFailIndexes"): 2472 enable_fail_indexes = [int(k) for k in raw_enabled_indexes] 2473 2474 return items.PlugItemState( 2475 item_hash=item_hash, 2476 insert_fail_indexes=insert_fail_indexes, 2477 enable_fail_indexes=enable_fail_indexes, 2478 is_enabled=payload["enabled"], 2479 can_insert=payload["canInsert"], 2480 )
The base deserialization factory class for all aiobungie objects.
Highly inspired hikari entity factory used to deserialize JSON responses from the REST client and turning them
into a aiobungie.crates Python classes.
73 def deserialize_bungie_user(self, data: typedefs.JSONObject) -> user.BungieUser: 74 return user.BungieUser( 75 id=int(data["membershipId"]), 76 created_at=time.clean_date(data["firstAccess"]), 77 name=data.get("cachedBungieGlobalDisplayName", undefined.UNDEFINED), 78 is_deleted=data["isDeleted"], 79 about=data["about"], 80 updated_at=time.clean_date(data["lastUpdate"]), 81 psn_name=data.get("psnDisplayName", None), 82 stadia_name=data.get("stadiaDisplayName", None), 83 steam_name=data.get("steamDisplayName", None), 84 twitch_name=data.get("twitchDisplayName", None), 85 blizzard_name=data.get("blizzardDisplayName", None), 86 status=data["statusText"], 87 locale=data["locale"], 88 picture=assets.Image(path=str(data["profilePicturePath"])), 89 code=data.get("cachedBungieGlobalDisplayNameCode", None), 90 unique_name=data.get("uniqueName", None), 91 theme_id=int(data["profileTheme"]), 92 show_activity=bool(data["showActivity"]), 93 theme_name=data["profileThemeName"], 94 display_title=data["userTitleDisplay"], 95 )
Deserialize a raw JSON Bungie.net user only payload into a user object.
This only returns the Bungie.net user and not the Destiny memberships.
Parameters
- data (
aiobungie.typedefs.JSONObject): The JSON data/payload.
Returns
aiobungie.crates.BungieUser: A Bungie user.
97 def deserialize_partial_bungie_user( 98 self, payload: typedefs.JSONObject 99 ) -> user.PartialBungieUser: 100 return user.PartialBungieUser( 101 net=self._net, 102 types=[ 103 enums.MembershipType(type_) 104 for type_ in payload.get("applicableMembershipTypes", []) 105 ], 106 name=payload.get("displayName", undefined.UNDEFINED), 107 id=int(payload["membershipId"]), 108 crossave_override=enums.MembershipType(payload["crossSaveOverride"]), 109 is_public=payload["isPublic"], 110 icon=assets.Image(payload.get("iconPath", "")), 111 type=enums.MembershipType(payload["membershipType"]), 112 )
Deserialize a raw JSON of a partial bungieNetUserInfo.
A partial user is a bungie.net user payload with missing information from
the main BungieUser object.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.PartialBungieUser: A partial bungie user.
114 def deserialize_destiny_membership( 115 self, payload: typedefs.JSONObject 116 ) -> user.DestinyMembership: 117 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 118 if ( 119 raw_name := payload.get("bungieGlobalDisplayName", "") 120 ) and not typedefs.is_unknown(raw_name): 121 name = raw_name 122 123 return user.DestinyMembership( 124 net=self._net, 125 id=int(payload["membershipId"]), 126 name=name, 127 code=payload.get("bungieGlobalDisplayNameCode", None), 128 last_seen_name=payload.get("LastSeenDisplayName") 129 or payload.get("displayName") # noqa: W503 130 or "", # noqa: W503 131 type=enums.MembershipType(payload["membershipType"]), 132 is_public=payload["isPublic"], 133 crossave_override=enums.MembershipType(payload["crossSaveOverride"]), 134 icon=assets.Image(payload.get("iconPath", "")), 135 types=[ 136 enums.MembershipType(type_) 137 for type_ in payload.get("applicableMembershipTypes", []) 138 ], 139 )
Deserialize a raw JSON of destinyUserInfo destiny membership information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.user.DestinyMembership: A Destiny 2 membership.
141 def deserialize_destiny_memberships( 142 self, data: typedefs.JSONArray 143 ) -> collections.Sequence[user.DestinyMembership]: 144 return [self.deserialize_destiny_membership(membership) for membership in data]
Deserialize a raw JSON payload/array of destinyUserInfo.
Parameters
- payload (
aiobungie.typedefs.JSONArray): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.user.DestinyMembership]: A sequence of Destiny 2 memberships.
146 def deserialize_user(self, data: typedefs.JSONObject) -> user.User: 147 primary_membership_id: typing.Optional[int] = None 148 if raw_primary_id := data.get("primaryMembershipId"): 149 primary_membership_id = int(raw_primary_id) 150 151 return user.User( 152 bungie=self.deserialize_bungie_user(data["bungieNetUser"]), 153 destiny=self.deserialize_destiny_memberships(data["destinyMemberships"]), 154 primary_membership_id=primary_membership_id, 155 )
Deserialize a raw JSON results of fetched user memberships and Bungie.net user its their id.
Parameters
- data (
aiobungie.typedefs.JSONObject): The JSON data/payload.
Returns
aiobungie.crates.User: A user object.
157 def deserialize_searched_user( 158 self, payload: typedefs.JSONObject 159 ) -> user.SearchableDestinyUser: 160 name: undefined.UndefinedOr[str] = undefined.UNDEFINED 161 if (raw_name := payload["bungieGlobalDisplayName"]) and not typedefs.is_unknown( 162 raw_name 163 ): 164 name = raw_name 165 166 code: typing.Optional[int] = None 167 if raw_code := payload.get("bungieGlobalDisplayNameCode"): 168 code = int(raw_code) 169 170 bungie_id: typing.Optional[int] = None 171 if raw_bungie_id := payload.get("bungieNetMembershipId"): 172 bungie_id = int(raw_bungie_id) 173 174 return user.SearchableDestinyUser( 175 name=name, 176 code=code, 177 bungie_id=bungie_id, 178 memberships=self.deserialize_destiny_memberships( 179 payload["destinyMemberships"] 180 ), 181 )
Deserialize the results of user search details.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.SearchableDestinyUser: The searched for Destiny 2 membership.
183 def deserialize_user_credentials( 184 self, payload: typedefs.JSONArray 185 ) -> collections.Sequence[user.UserCredentials]: 186 return [ 187 user.UserCredentials( 188 type=enums.CredentialType(int(creds["credentialType"])), 189 display_name=creds["credentialDisplayName"], 190 is_public=creds["isPublic"], 191 self_as_string=creds.get("credentialAsString", undefined.UNDEFINED), 192 ) 193 for creds in payload 194 ]
Deserialize a JSON array of Bungie user credentials.
Parameters
- payload (
aiobungie.typedefs.JSONArray): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.UserCredentials]: A sequence of user's credentials.
196 def deserialize_user_themes( 197 self, payload: typedefs.JSONArray 198 ) -> collections.Sequence[user.UserThemes]: 199 return [ 200 user.UserThemes( 201 id=int(entry["userThemeId"]), 202 name=entry["userThemeName"] 203 if "userThemeName" in entry 204 else undefined.UNDEFINED, 205 description=entry["userThemeDescription"] 206 if "userThemeDescription" in entry 207 else undefined.UNDEFINED, 208 ) 209 for entry in payload 210 ]
Deserialize a raw JSON array of Bungie user themes.
Parameters
- payload (
aiobungie.typedefs.JSONArray): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.user.UserThemes]: A sequence of bungie user themes.
212 def deserialize_clan(self, payload: typedefs.JSONObject) -> clans.Clan: 213 # This is kinda redundant 214 data = payload 215 216 # This is always outside the details. 217 current_user_map: typing.Optional[ 218 collections.Mapping[str, clans.ClanMember] 219 ] = None 220 if raw_current_user_map := payload.get("currentUserMemberMap"): 221 current_user_map = { 222 membership_type: self.deserialize_clan_member(membership) 223 for membership_type, membership in raw_current_user_map.items() 224 } 225 226 try: 227 data = payload["detail"] 228 except KeyError: 229 pass 230 231 id = data["groupId"] 232 name = data["name"] 233 created_at = data["creationDate"] 234 member_count = data["memberCount"] 235 about = data["about"] 236 motto = data["motto"] 237 is_public = data["isPublic"] 238 banner = assets.Image(str(data["bannerPath"])) 239 avatar = assets.Image(str(data["avatarPath"])) 240 tags = data["tags"] 241 type = data["groupType"] 242 243 features = data["features"] 244 features_obj = clans.ClanFeatures( 245 max_members=features["maximumMembers"], 246 max_membership_types=features["maximumMembershipsOfGroupType"], 247 capabilities=features["capabilities"], 248 membership_types=features["membershipTypes"], 249 invite_permissions=features["invitePermissionOverride"], 250 update_banner_permissions=features["updateBannerPermissionOverride"], 251 update_culture_permissions=features["updateCulturePermissionOverride"], 252 join_level=features["joinLevel"], 253 ) 254 255 information: typedefs.JSONObject = data["clanInfo"] 256 progression: collections.Mapping[int, progressions.Progression] = { 257 int(prog_hash): self.deserialize_progressions(prog) 258 for prog_hash, prog in information["d2ClanProgressions"].items() 259 } 260 261 founder: typedefs.NoneOr[clans.ClanMember] = None 262 if raw_founder := payload.get("founder"): 263 founder = self.deserialize_clan_member(raw_founder) 264 265 return clans.Clan( 266 net=self._net, 267 id=int(id), 268 name=name, 269 type=enums.GroupType(type), 270 created_at=time.clean_date(created_at), 271 member_count=member_count, 272 motto=motto, 273 about=about, 274 is_public=is_public, 275 banner=banner, 276 avatar=avatar, 277 tags=tags, 278 features=features_obj, 279 owner=founder, 280 progressions=progression, 281 call_sign=information["clanCallsign"], 282 banner_data=information["clanBannerData"], 283 chat_security=data["chatSecurity"], 284 conversation_id=int(data["conversationId"]), 285 allow_chat=data["allowChat"], 286 theme=data["theme"], 287 current_user_membership=current_user_map, 288 )
Deserialize a raw JSON payload of Bungie clan information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.Clan: A clan owner.
290 def deserialize_clan_member(self, data: typedefs.JSONObject, /) -> clans.ClanMember: 291 destiny_user = self.deserialize_destiny_membership(data["destinyUserInfo"]) 292 return clans.ClanMember( 293 net=self._net, 294 last_seen_name=destiny_user.last_seen_name, 295 id=destiny_user.id, 296 name=destiny_user.name, 297 icon=destiny_user.icon, 298 last_online=time.from_timestamp(int(data["lastOnlineStatusChange"])), 299 group_id=int(data["groupId"]), 300 joined_at=time.clean_date(data["joinDate"]), 301 types=destiny_user.types, 302 is_public=destiny_user.is_public, 303 type=destiny_user.type, 304 code=destiny_user.code, 305 is_online=data["isOnline"], 306 crossave_override=destiny_user.crossave_override, 307 bungie=self.deserialize_partial_bungie_user(data["bungieNetUserInfo"]) 308 if "bungieNetUserInfo" in data 309 else None, 310 member_type=enums.ClanMemberType(int(data["memberType"])), 311 )
Deserialize a JSON payload of a clan member information.
Parameters
- data (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.ClanMember: A clan member.
313 def deserialize_clan_members( 314 self, data: typedefs.JSONObject, / 315 ) -> iterators.Iterator[clans.ClanMember]: 316 return iterators.Iterator( 317 [self.deserialize_clan_member(member) for member in data["results"]] 318 )
Deserialize a JSON payload of a clan members information.
Parameters
- data (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.ClanMember]: An iterator of clan members of the deserialized payload.
320 def deserialize_group_member( 321 self, payload: typedefs.JSONObject 322 ) -> clans.GroupMember: 323 member = payload["member"] 324 return clans.GroupMember( 325 net=self._net, 326 join_date=time.clean_date(member["joinDate"]), 327 group_id=int(member["groupId"]), 328 member_type=enums.ClanMemberType(member["memberType"]), 329 is_online=member["isOnline"], 330 last_online=time.from_timestamp(int(member["lastOnlineStatusChange"])), 331 inactive_memberships=payload.get("areAllMembershipsInactive", None), 332 member=self.deserialize_destiny_membership(member["destinyUserInfo"]), 333 group=self.deserialize_clan(payload["group"]), 334 )
Deserialize a JSON payload of group information for a member.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.typedefs.NoneOr[aiobungie.crates.GroupMember]: A group member. This can returnNoneif nothing was found.
352 def deserialize_clan_conversations( 353 self, payload: typedefs.JSONArray 354 ) -> collections.Sequence[clans.ClanConversation]: 355 return [self._deserialize_clan_conversation(conv) for conv in payload]
Deserialize a JSON array of a clan conversations information.
Parameters
- payload (
aiobungie.typedefs.JSONArray): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.ClanConversation]: A sequence of clan conversations of the deserialized payload.
357 def deserialize_app_owner( 358 self, payload: typedefs.JSONObject 359 ) -> application.ApplicationOwner: 360 return application.ApplicationOwner( 361 net=self._net, 362 name=payload.get("bungieGlobalDisplayName", undefined.UNDEFINED), 363 id=int(payload["membershipId"]), 364 type=enums.MembershipType(payload["membershipType"]), 365 icon=assets.Image(str(payload["iconPath"])), 366 is_public=payload["isPublic"], 367 code=payload.get("bungieGlobalDisplayNameCode", None), 368 )
Deserialize a JSON payload of Bungie Developer portal application owner information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.application.ApplicationOwner: An application owner.
370 def deserialize_app(self, payload: typedefs.JSONObject) -> application.Application: 371 return application.Application( 372 id=int(payload["applicationId"]), 373 name=payload["name"], 374 link=payload["link"], 375 status=payload["status"], 376 redirect_url=payload.get("redirectUrl", None), 377 created_at=time.clean_date(str(payload["creationDate"])), 378 published_at=time.clean_date(str(payload["firstPublished"])), 379 owner=self.deserialize_app_owner(payload["team"][0]["user"]), # type: ignore 380 scope=payload.get("scope", undefined.UNDEFINED), 381 )
Deserialize a JSON payload of Bungie Developer portal application information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.application.Application: An application.
404 def deserialize_profile( 405 self, payload: typedefs.JSONObject, / 406 ) -> typing.Optional[profile.Profile]: 407 if (raw_profile := payload.get("data")) is None: 408 return None 409 410 payload = raw_profile 411 id = int(payload["userInfo"]["membershipId"]) 412 name = payload["userInfo"]["displayName"] 413 is_public = payload["userInfo"]["isPublic"] 414 type = enums.MembershipType(payload["userInfo"]["membershipType"]) 415 last_played = time.clean_date(str(payload["dateLastPlayed"])) 416 character_ids = [int(cid) for cid in payload["characterIds"]] 417 power_cap = payload["currentSeasonRewardPowerCap"] 418 419 return profile.Profile( 420 id=int(id), 421 name=name, 422 is_public=is_public, 423 type=type, 424 last_played=last_played, 425 character_ids=character_ids, 426 power_cap=power_cap, 427 net=self._net, 428 )
Deserialize a JSON payload of Bungie.net profile information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
typing.Optional[aiobungie.crates.Profile]: A profile.
430 def deserialize_profile_item( 431 self, payload: typedefs.JSONObject 432 ) -> profile.ProfileItemImpl: 433 instance_id: typing.Optional[int] = None 434 if raw_instance_id := payload.get("itemInstanceId"): 435 instance_id = int(raw_instance_id) 436 437 version_number: typing.Optional[int] = None 438 if raw_version := payload.get("versionNumber"): 439 version_number = int(raw_version) 440 441 transfer_status = enums.TransferStatus(payload["transferStatus"]) 442 443 return profile.ProfileItemImpl( 444 net=self._net, 445 hash=payload["itemHash"], 446 quantity=payload["quantity"], 447 bind_status=enums.ItemBindStatus(payload["bindStatus"]), 448 location=enums.ItemLocation(payload["location"]), 449 bucket=payload["bucketHash"], 450 transfer_status=transfer_status, 451 lockable=payload["lockable"], 452 state=enums.ItemState(payload["state"]), 453 dismantel_permissions=payload["dismantlePermission"], 454 is_wrapper=payload["isWrapper"], 455 instance_id=instance_id, 456 version_number=version_number, 457 ornament_id=payload.get("overrideStyleItemHash"), 458 )
Deserialize a JSON payload of a singular profile component item.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.ProfileItemImpl: Implementation of a Destiny 2 profile component item.
460 def deserialize_objectives(self, payload: typedefs.JSONObject) -> records.Objective: 461 return records.Objective( 462 net=self._net, 463 hash=payload["objectiveHash"], 464 visible=payload["visible"], 465 complete=payload["complete"], 466 completion_value=payload["completionValue"], 467 progress=payload.get("progress"), 468 destination_hash=payload.get("destinationHash"), 469 activity_hash=payload.get("activityHash"), 470 )
Deserialize a JSON payload of an objective found in a record profile component.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.records.Objective: A record objective object.
472 def deserialize_records( 473 self, 474 payload: typedefs.JSONObject, 475 scores: typing.Optional[records.RecordScores] = None, 476 **nodes: int, 477 ) -> records.Record: 478 objectives: typing.Optional[list[records.Objective]] = None 479 interval_objectives: typing.Optional[list[records.Objective]] = None 480 record_state: typedefs.IntAnd[records.RecordState] 481 482 record_state = records.RecordState(payload["state"]) 483 484 if raw_objs := payload.get("objectives"): 485 objectives = [self.deserialize_objectives(obj) for obj in raw_objs] 486 487 if raw_interval_objs := payload.get("intervalObjectives"): 488 interval_objectives = [ 489 self.deserialize_objectives(obj) for obj in raw_interval_objs 490 ] 491 492 return records.Record( 493 scores=scores, 494 categories_node_hash=nodes.get("categories_hash", undefined.UNDEFINED), 495 seals_node_hash=nodes.get("seals_hash", undefined.UNDEFINED), 496 state=record_state, 497 objectives=objectives, 498 interval_objectives=interval_objectives, 499 redeemed_count=payload.get("intervalsRedeemedCount", 0), 500 completion_times=payload.get("completedCount", None), 501 reward_visibility=payload.get("rewardVisibilty", None), 502 )
Deserialize a JSON object of a profile record component.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON object payload - scores (
typing.Optional[records.RecordScores]): The records scores object. This exists only to keep the signature ofaiobungie.crates.CharacterRecordwith the record object. As it will always beNonein that object. - **nodes (
int): An int kwargs use to grab the node hashes while deserializing components.
Returns
aiobungie.records.Record: A standard implementation of a profile record component.
504 def deserialize_character_records( 505 self, 506 payload: typedefs.JSONObject, 507 scores: typing.Optional[records.RecordScores] = None, 508 record_hashes: typing.Optional[list[int]] = None, 509 ) -> records.CharacterRecord: 510 record = self.deserialize_records(payload, scores) 511 return records.CharacterRecord( 512 scores=scores, 513 categories_node_hash=record.categories_node_hash, 514 seals_node_hash=record.seals_node_hash, 515 state=record.state, 516 objectives=record.objectives, 517 interval_objectives=record.interval_objectives, 518 redeemed_count=payload.get("intervalsRedeemedCount", 0), 519 completion_times=payload.get("completedCount"), 520 reward_visibility=payload.get("rewardVisibilty"), 521 record_hashes=record_hashes or [], 522 )
Deserialize a JSON object of a profile character record component.
This almost does the same this as deserialize_records but
has more fields which can only be found in a character record.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON object payload
Returns
aiobungie.records.CharacterRecord: A standard implementation of a profile character record component.
524 def deserialize_character_dye(self, payload: typedefs.JSONObject) -> character.Dye: 525 return character.Dye( 526 channel_hash=payload["channelHash"], dye_hash=payload["dyeHash"] 527 )
Deserialize a JSON payload of a character's dye information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.character.Dye: Information about a character dye object.
529 def deserialize_character_customization( 530 self, payload: typedefs.JSONObject 531 ) -> character.CustomizationOptions: 532 return character.CustomizationOptions( 533 personality=payload["personality"], 534 face=payload["face"], 535 skin_color=payload["skinColor"], 536 lip_color=payload["lipColor"], 537 eye_color=payload["eyeColor"], 538 hair_colors=payload.get("hairColors", []), 539 feature_colors=payload.get("featureColors", []), 540 decal_color=payload["decalColor"], 541 wear_helmet=payload["wearHelmet"], 542 hair_index=payload["hairIndex"], 543 feature_index=payload["featureIndex"], 544 decal_index=payload["decalIndex"], 545 )
Deserialize a JSON payload of a character customization information found in character render data profile component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.character.CustomizationOptions: Information about a character customs object.
547 def deserialize_character_minimal_equipments( 548 self, payload: typedefs.JSONObject 549 ) -> character.MinimalEquipments: 550 dyes = None 551 if raw_dyes := payload.get("dyes"): 552 if raw_dyes: 553 dyes = [self.deserialize_character_dye(dye) for dye in raw_dyes] 554 return character.MinimalEquipments( 555 net=self._net, item_hash=payload["itemHash"], dyes=dyes 556 )
Deserialize a singular JSON peer view of equipment found in character render data profile component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.character.MinimalEquipments: A minimal equipment object.
558 def deserialize_character_render_data( 559 self, payload: typedefs.JSONObject, / 560 ) -> character.RenderedData: 561 return character.RenderedData( 562 net=self._net, 563 customization=self.deserialize_character_customization( 564 payload["customization"] 565 ), 566 custom_dyes=[ 567 self.deserialize_character_dye(dye) 568 for dye in payload["customDyes"] 569 if dye 570 ], 571 equipment=[ 572 self.deserialize_character_minimal_equipments(equipment) 573 for equipment in payload["peerView"]["equipment"] 574 ], 575 )
Deserialize a JSON payload of a profile character render data component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.RenderedData: A character rendered data profile component.
577 def deserialize_available_activity( 578 self, payload: typedefs.JSONObject 579 ) -> activity.AvailableActivity: 580 return activity.AvailableActivity( 581 hash=payload["activityHash"], 582 is_new=payload["isNew"], 583 is_completed=payload["isCompleted"], 584 is_visible=payload["isVisible"], 585 display_level=payload.get("displayLevel"), 586 recommended_light=payload.get("recommendedLight"), 587 difficulty=activity.Difficulty(payload["difficultyTier"]), 588 can_join=payload["canJoin"], 589 can_lead=payload["canLead"], 590 )
Deserialize a JSON payload of an available activities.
This method is used to deserialize an array of aiobungie.crates.CharacterActivity.available_activities.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.AvailableActivity: An available activity object.
592 def deserialize_character_activity( 593 self, payload: typedefs.JSONObject 594 ) -> activity.CharacterActivity: 595 current_mode: typing.Optional[enums.GameMode] = None 596 if raw_current_mode := payload.get("currentActivityModeType"): 597 current_mode = enums.GameMode(raw_current_mode) 598 599 current_mode_types: typing.Optional[collections.Sequence[enums.GameMode]] = None 600 if raw_current_modes := payload.get("currentActivityModeTypes"): 601 current_mode_types = [enums.GameMode(type_) for type_ in raw_current_modes] 602 603 return activity.CharacterActivity( 604 date_started=time.clean_date(payload["dateActivityStarted"]), 605 current_hash=payload["currentActivityHash"], 606 current_mode_hash=payload["currentActivityModeHash"], 607 current_mode=current_mode, 608 current_mode_hashes=payload.get("currentActivityModeHashes"), 609 current_mode_types=current_mode_types, 610 current_playlist_hash=payload.get("currentPlaylistActivityHash"), 611 last_story_hash=payload["lastCompletedStoryHash"], 612 available_activities=[ 613 self.deserialize_available_activity(activity_) 614 for activity_ in payload["availableActivities"] 615 ], 616 )
Deserialize a JSON payload of character activity profile component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.CharacterActivity: A character activities component object.
618 def deserialize_profile_items( 619 self, payload: typedefs.JSONObject, / 620 ) -> list[profile.ProfileItemImpl]: 621 return [self.deserialize_profile_item(item) for item in payload["items"]]
Deserialize a JSON payload of profile items component information.
This may deserialize profileInventories or profileCurrencies or any
other alternatives.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
typing.Optional[collections.Sequence[aiobungie.crates.ProfileItemImpl]]: A profile component object that contains items of the deserialized payload.
664 def deserialize_progressions( 665 self, payload: typedefs.JSONObject 666 ) -> progressions.Progression: 667 return progressions.Progression( 668 hash=int(payload["progressionHash"]), 669 level=int(payload["level"]), 670 cap=int(payload["levelCap"]), 671 daily_limit=int(payload["dailyLimit"]), 672 weekly_limit=int(payload["weeklyLimit"]), 673 current_progress=int(payload["currentProgress"]), 674 daily_progress=int(payload["dailyProgress"]), 675 needed=int(payload["progressToNextLevel"]), 676 next_level=int(payload["nextLevelAt"]), 677 )
764 def deserialize_milestone( 765 self, payload: typedefs.JSONObject 766 ) -> milestones.Milestone: 767 start_date: typing.Optional[datetime.datetime] = None 768 if raw_start_date := payload.get("startDate"): 769 start_date = time.clean_date(raw_start_date) 770 771 end_date: typing.Optional[datetime.datetime] = None 772 if raw_end_date := payload.get("endDate"): 773 end_date = time.clean_date(raw_end_date) 774 775 rewards: typing.Optional[ 776 collections.Collection[milestones.MilestoneReward] 777 ] = None 778 if raw_rewards := payload.get("rewards"): 779 rewards = [ 780 self._deserialize_milestone_rewards(reward) for reward in raw_rewards 781 ] 782 783 activities: typing.Optional[ 784 collections.Sequence[milestones.MilestoneActivity] 785 ] = None 786 if raw_activities := payload.get("activities"): 787 activities = [ 788 self._deserialize_milestone_activity(active) 789 for active in raw_activities 790 ] 791 792 quests: typing.Optional[collections.Sequence[milestones.MilestoneQuest]] = None 793 if raw_quests := payload.get("availableQuests"): 794 quests = [ 795 self._deserialize_milestone_available_quest(quest) 796 for quest in raw_quests 797 ] 798 799 vendors: typing.Optional[ 800 collections.Sequence[milestones.MilestoneVendor] 801 ] = None 802 if raw_vendors := payload.get("vendors"): 803 vendors = [ 804 milestones.MilestoneVendor( 805 vendor_hash=vendor["vendorHash"], 806 preview_itemhash=vendor.get("previewItemHash"), 807 ) 808 for vendor in raw_vendors 809 ] 810 811 return milestones.Milestone( 812 hash=payload["milestoneHash"], 813 start_date=start_date, 814 end_date=end_date, 815 order=payload["order"], 816 rewards=rewards, 817 available_quests=quests, 818 activities=activities, 819 vendors=vendors, 820 )
874 def deserialize_character_progressions( 875 self, payload: typedefs.JSONObject 876 ) -> character.CharacterProgression: 877 progressions_ = { 878 int(prog_id): self.deserialize_progressions(prog) 879 for prog_id, prog in payload["progressions"].items() 880 } 881 882 factions = { 883 int(faction_id): self._deserialize_factions(faction) 884 for faction_id, faction in payload["factions"].items() 885 } 886 887 milestones_ = { 888 int(milestone_hash): self.deserialize_milestone(milestone) 889 for milestone_hash, milestone in payload["milestones"].items() 890 } 891 892 uninstanced_item_objectives = { 893 int(item_hash): [self.deserialize_objectives(ins) for ins in obj] 894 for item_hash, obj in payload["uninstancedItemObjectives"].items() 895 } 896 897 artifact = payload["seasonalArtifact"] 898 seasonal_artifact = season.CharacterScopedArtifact( 899 hash=artifact["artifactHash"], 900 points_used=artifact["pointsUsed"], 901 reset_count=artifact["resetCount"], 902 tiers=[ 903 self._deserialize_artifact_tiers(tier) for tier in artifact["tiers"] 904 ], 905 ) 906 checklists = payload["checklists"] 907 908 return character.CharacterProgression( 909 progressions=progressions_, 910 factions=factions, 911 checklists=checklists, 912 milestones=milestones_, 913 seasonal_artifact=seasonal_artifact, 914 uninstanced_item_objectives=uninstanced_item_objectives, 915 )
917 def deserialize_character_progressions_mapping( 918 self, payload: typedefs.JSONObject 919 ) -> collections.Mapping[int, character.CharacterProgression]: 920 character_progressions: collections.Mapping[ 921 int, character.CharacterProgression 922 ] = {} 923 for char_id, data in payload["data"].items(): 924 # A little hack to stop mypy complaining about Mapping <-> dict 925 character_progressions[int(char_id)] = self.deserialize_character_progressions(data) # type: ignore[index] 926 return character_progressions
928 def deserialize_characters_records( 929 self, 930 payload: typedefs.JSONObject, 931 ) -> collections.Mapping[int, records.CharacterRecord]: 932 return { 933 int(rec_id): self.deserialize_character_records( 934 rec, record_hashes=payload.get("featuredRecordHashes") 935 ) 936 for rec_id, rec in payload["records"].items() 937 }
939 def deserialize_profile_records( 940 self, payload: typedefs.JSONObject 941 ) -> collections.Mapping[int, records.Record]: 942 raw_profile_records = payload["data"] 943 scores = records.RecordScores( 944 current_score=raw_profile_records["score"], 945 legacy_score=raw_profile_records["legacyScore"], 946 lifetime_score=raw_profile_records["lifetimeScore"], 947 ) 948 return { 949 int(record_id): self.deserialize_records( 950 record, 951 scores, 952 categories_hash=raw_profile_records["recordCategoriesRootNodeHash"], 953 seals_hash=raw_profile_records["recordSealsRootNodeHash"], 954 ) 955 for record_id, record in raw_profile_records["records"].items() 956 }
991 def deserialize_craftables_component( 992 self, payload: typedefs.JSONObject 993 ) -> components.CraftablesComponent: 994 return components.CraftablesComponent( 995 net=self._net, 996 craftables={ 997 int(item_id): self._deserialize_craftable_item(item) 998 for item_id, item in payload["craftables"].items() 999 if item is not None 1000 }, 1001 crafting_root_node_hash=payload["craftingRootNodeHash"], 1002 )
1004 def deserialize_components( # noqa: C901 Too complex. 1005 self, payload: typedefs.JSONObject 1006 ) -> components.Component: 1007 profile_: typing.Optional[profile.Profile] = None 1008 if raw_profile := payload.get("profile"): 1009 profile_ = self.deserialize_profile(raw_profile) 1010 1011 profile_progression: typing.Optional[profile.ProfileProgression] = None 1012 if raw_profile_progression := payload.get("profileProgression"): 1013 profile_progression = self.deserialize_profile_progression( 1014 raw_profile_progression 1015 ) 1016 1017 profile_currencies: typing.Optional[ 1018 collections.Sequence[profile.ProfileItemImpl] 1019 ] = None 1020 if raw_profile_currencies := payload.get("profileCurrencies"): 1021 if "data" in raw_profile_currencies: 1022 profile_currencies = self.deserialize_profile_items( 1023 raw_profile_currencies["data"] 1024 ) 1025 1026 profile_inventories: typing.Optional[ 1027 collections.Sequence[profile.ProfileItemImpl] 1028 ] = None 1029 if raw_profile_inventories := payload.get("profileInventory"): 1030 if "data" in raw_profile_inventories: 1031 profile_inventories = self.deserialize_profile_items( 1032 raw_profile_inventories["data"] 1033 ) 1034 1035 profile_records: typing.Optional[ 1036 collections.Mapping[int, records.Record] 1037 ] = None 1038 1039 if raw_profile_records_ := payload.get("profileRecords"): 1040 profile_records = self.deserialize_profile_records(raw_profile_records_) 1041 1042 characters: typing.Optional[typing.Mapping[int, character.Character]] = None 1043 if raw_characters := payload.get("characters"): 1044 characters = self.deserialize_characters(raw_characters) 1045 1046 character_records: typing.Optional[ 1047 collections.Mapping[int, records.CharacterRecord] 1048 ] = None 1049 1050 if raw_character_records := payload.get("characterRecords"): 1051 # Had to do it in two steps.. 1052 to_update: typedefs.JSONObject = {} 1053 for _, data in raw_character_records["data"].items(): 1054 for record_id, record in data.items(): 1055 to_update[record_id] = record 1056 1057 character_records = { 1058 int(rec_id): self.deserialize_character_records( 1059 rec, record_hashes=to_update.get("featuredRecordHashes") 1060 ) 1061 for rec_id, rec in to_update["records"].items() 1062 } 1063 1064 character_equipments: typing.Optional[ 1065 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] 1066 ] = None 1067 if raw_character_equips := payload.get("characterEquipment"): 1068 character_equipments = self.deserialize_character_equipments( 1069 raw_character_equips 1070 ) 1071 1072 character_inventories: typing.Optional[ 1073 collections.Mapping[int, collections.Sequence[profile.ProfileItemImpl]] 1074 ] = None 1075 if raw_character_inventories := payload.get("characterInventories"): 1076 if "data" in raw_character_inventories: 1077 character_inventories = self.deserialize_character_equipments( 1078 raw_character_inventories 1079 ) 1080 1081 character_activities: typing.Optional[ 1082 collections.Mapping[int, activity.CharacterActivity] 1083 ] = None 1084 if raw_char_acts := payload.get("characterActivities"): 1085 character_activities = self.deserialize_character_activities(raw_char_acts) 1086 1087 character_render_data: typing.Optional[ 1088 collections.Mapping[int, character.RenderedData] 1089 ] = None 1090 if raw_character_render_data := payload.get("characterRenderData"): 1091 character_render_data = self.deserialize_characters_render_data( 1092 raw_character_render_data 1093 ) 1094 1095 character_progressions: typing.Optional[ 1096 collections.Mapping[int, character.CharacterProgression] 1097 ] = None 1098 1099 if raw_character_progressions := payload.get("characterProgressions"): 1100 character_progressions = self.deserialize_character_progressions_mapping( 1101 raw_character_progressions 1102 ) 1103 1104 profile_string_vars: typing.Optional[collections.Mapping[int, int]] = None 1105 if raw_profile_string_vars := payload.get("profileStringVariables"): 1106 profile_string_vars = raw_profile_string_vars["data"]["integerValuesByHash"] 1107 1108 character_string_vars: typing.Optional[ 1109 collections.Mapping[int, collections.Mapping[int, int]] 1110 ] = None 1111 if raw_character_string_vars := payload.get("characterStringVariables"): 1112 character_string_vars = { 1113 int(char_id): data["integerValuesByHash"] 1114 for char_id, data in raw_character_string_vars["data"].items() 1115 } 1116 1117 metrics: typing.Optional[ 1118 collections.Sequence[ 1119 collections.Mapping[ 1120 int, tuple[bool, typing.Optional[records.Objective]] 1121 ] 1122 ] 1123 ] = None 1124 root_node_hash: typing.Optional[int] = None 1125 1126 if raw_metrics := payload.get("metrics"): 1127 root_node_hash = raw_metrics["data"]["metricsRootNodeHash"] 1128 metrics = [ 1129 { 1130 int(metrics_hash): ( 1131 data["invisible"], 1132 self.deserialize_objectives(data["objectiveProgress"]) 1133 if "objectiveProgress" in data 1134 else None, 1135 ) 1136 for metrics_hash, data in raw_metrics["data"]["metrics"].items() 1137 } 1138 ] 1139 transitory: typing.Optional[fireteams.FireteamParty] = None 1140 if raw_transitory := payload.get("profileTransitoryData"): 1141 if "data" in raw_transitory: 1142 transitory = self.deserialize_fireteam_party(raw_transitory["data"]) 1143 1144 item_components: typing.Optional[components.ItemsComponent] = None 1145 if raw_item_components := payload.get("itemComponents"): 1146 item_components = self.deserialize_items_component(raw_item_components) 1147 1148 profile_plugsets: typing.Optional[ 1149 collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1150 ] = None 1151 1152 if raw_profile_plugs := payload.get("profilePlugSets"): 1153 profile_plugsets = { 1154 int(index): [self.deserialize_plug_item_state(state) for state in data] 1155 for index, data in raw_profile_plugs["data"]["plugs"].items() 1156 } 1157 1158 character_plugsets: typing.Optional[ 1159 collections.Mapping[ 1160 int, collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1161 ] 1162 ] = None 1163 if raw_char_plugsets := payload.get("characterPlugSets"): 1164 character_plugsets = { 1165 int(char_id): { 1166 int(index): [ 1167 self.deserialize_plug_item_state(state) for state in data 1168 ] 1169 for index, data in inner["plugs"].items() 1170 } 1171 for char_id, inner in raw_char_plugsets["data"].items() 1172 } 1173 1174 character_collectibles: typing.Optional[ 1175 collections.Mapping[int, items.Collectible] 1176 ] = None 1177 if raw_character_collectibles := payload.get("characterCollectibles"): 1178 character_collectibles = { 1179 int(char_id): self._deserialize_collectible(data) 1180 for char_id, data in raw_character_collectibles["data"].items() 1181 } 1182 1183 profile_collectibles: typing.Optional[items.Collectible] = None 1184 if raw_profile_collectibles := payload.get("profileCollectibles"): 1185 profile_collectibles = self._deserialize_collectible( 1186 raw_profile_collectibles["data"] 1187 ) 1188 1189 profile_nodes: typing.Optional[collections.Mapping[int, records.Node]] = None 1190 if raw_profile_nodes := payload.get("profilePresentationNodes"): 1191 profile_nodes = { 1192 int(node_hash): self._deserialize_node(node) 1193 for node_hash, node in raw_profile_nodes["data"]["nodes"].items() 1194 } 1195 1196 character_nodes: typing.Optional[ 1197 collections.Mapping[int, collections.Mapping[int, records.Node]] 1198 ] = None 1199 if raw_character_nodes := payload.get("characterPresentationNodes"): 1200 character_nodes = { 1201 int(char_id): { 1202 int(node_hash): self._deserialize_node(node) 1203 for node_hash, node in each_character["nodes"].items() 1204 } 1205 for char_id, each_character in raw_character_nodes["data"].items() 1206 } 1207 1208 platform_silver: typing.Optional[ 1209 collections.Mapping[str, profile.ProfileItemImpl] 1210 ] = None 1211 if raw_platform_silver := payload.get("platformSilver"): 1212 if "data" in raw_platform_silver: 1213 platform_silver = { 1214 platform_name: self.deserialize_profile_item(item) 1215 for platform_name, item in raw_platform_silver["data"][ 1216 "platformSilver" 1217 ].items() 1218 } 1219 1220 character_currency_lookups: typing.Optional[ 1221 collections.Mapping[int, collections.Sequence[items.Currency]] 1222 ] = None 1223 if raw_char_lookups := payload.get("characterCurrencyLookups"): 1224 if "data" in raw_char_lookups: 1225 character_currency_lookups = { 1226 int(char_id): self._deserialize_currencies(currencie) 1227 for char_id, currencie in raw_char_lookups["data"].items() 1228 } 1229 1230 character_craftables: typing.Optional[ 1231 collections.Mapping[int, components.CraftablesComponent] 1232 ] = None 1233 if raw_character_craftables := payload.get("characterCraftables"): 1234 if "data" in raw_character_craftables: 1235 character_craftables = { 1236 int(char_id): self.deserialize_craftables_component(craftable) 1237 for char_id, craftable in raw_character_craftables["data"].items() 1238 } 1239 1240 return components.Component( 1241 profiles=profile_, 1242 profile_progression=profile_progression, 1243 profile_currencies=profile_currencies, 1244 profile_inventories=profile_inventories, 1245 profile_records=profile_records, 1246 characters=characters, 1247 character_records=character_records, 1248 character_equipments=character_equipments, 1249 character_inventories=character_inventories, 1250 character_activities=character_activities, 1251 character_render_data=character_render_data, 1252 character_progressions=character_progressions, 1253 profile_string_variables=profile_string_vars, 1254 character_string_variables=character_string_vars, 1255 metrics=metrics, 1256 root_node_hash=root_node_hash, 1257 transitory=transitory, 1258 item_components=item_components, 1259 profile_plugsets=profile_plugsets, 1260 character_plugsets=character_plugsets, 1261 character_collectibles=character_collectibles, 1262 profile_collectibles=profile_collectibles, 1263 profile_nodes=profile_nodes, 1264 character_nodes=character_nodes, 1265 platform_silver=platform_silver, 1266 character_currency_lookups=character_currency_lookups, 1267 character_craftables=character_craftables, 1268 )
Deserialize a JSON payload of Bungie.net profile components information.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.Component: A component implementation that includes all other components of the deserialized payload.
1270 def deserialize_items_component( 1271 self, payload: typedefs.JSONObject 1272 ) -> components.ItemsComponent: 1273 instances: typing.Optional[ 1274 collections.Sequence[collections.Mapping[int, items.ItemInstance]] 1275 ] = None 1276 if raw_instances := payload.get("instances"): 1277 instances = [ 1278 { 1279 int(ins_id): self.deserialize_instanced_item(item) 1280 for ins_id, item in raw_instances["data"].items() 1281 } 1282 ] 1283 1284 render_data: typing.Optional[ 1285 collections.Mapping[int, tuple[bool, dict[int, int]]] 1286 ] = None 1287 if raw_render_data := payload.get("renderData"): 1288 render_data = { 1289 int(ins_id): (data["useCustomDyes"], data["artRegions"]) 1290 for ins_id, data in raw_render_data["data"].items() 1291 } 1292 1293 stats: typing.Optional[collections.Mapping[int, items.ItemStatsView]] = None 1294 if raw_stats := payload.get("stats"): 1295 builder: collections.Mapping[int, items.ItemStatsView] = {} 1296 for ins_id, stat in raw_stats["data"].items(): 1297 for _, items_ in stat.items(): 1298 builder[int(ins_id)] = self.deserialize_item_stats_view(items_) # type: ignore[index] 1299 stats = builder 1300 1301 sockets: typing.Optional[ 1302 collections.Mapping[int, collections.Sequence[items.ItemSocket]] 1303 ] = None 1304 if raw_sockets := payload.get("sockets"): 1305 sockets = { 1306 int(ins_id): [ 1307 self.deserialize_item_socket(socket) for socket in item["sockets"] 1308 ] 1309 for ins_id, item in raw_sockets["data"].items() 1310 } 1311 1312 objeectives: typing.Optional[ 1313 collections.Mapping[int, collections.Sequence[records.Objective]] 1314 ] = None 1315 if raw_objectives := payload.get("objectives"): 1316 objeectives = { 1317 int(ins_id): [self.deserialize_objectives(objective)] 1318 for ins_id, data in raw_objectives["data"].items() 1319 for objective in data["objectives"] 1320 } 1321 1322 perks: typing.Optional[ 1323 collections.Mapping[int, collections.Collection[items.ItemPerk]] 1324 ] = None 1325 if raw_perks := payload.get("perks"): 1326 perks = { 1327 int(ins_id): [ 1328 self.deserialize_item_perk(perk) for perk in item["perks"] 1329 ] 1330 for ins_id, item in raw_perks["data"].items() 1331 } 1332 1333 plug_states: typing.Optional[collections.Sequence[items.PlugItemState]] = None 1334 if raw_plug_states := payload.get("plugStates"): 1335 pending_states: list[items.PlugItemState] = [] 1336 for _, plug in raw_plug_states["data"].items(): 1337 pending_states.append(self.deserialize_plug_item_state(plug)) 1338 plug_states = pending_states 1339 1340 reusable_plugs: typing.Optional[ 1341 collections.Mapping[int, collections.Sequence[items.PlugItemState]] 1342 ] = None 1343 if raw_re_plugs := payload.get("reusablePlugs"): 1344 reusable_plugs = { 1345 int(ins_id): [ 1346 self.deserialize_plug_item_state(state) for state in inner 1347 ] 1348 for ins_id, plug in raw_re_plugs["data"].items() 1349 for inner in list(plug["plugs"].values()) 1350 } 1351 1352 plug_objectives: typing.Optional[ 1353 collections.Mapping[ 1354 int, collections.Mapping[int, collections.Collection[records.Objective]] 1355 ] 1356 ] = None 1357 if raw_plug_objectives := payload.get("plugObjectives"): 1358 plug_objectives = { 1359 int(ins_id): { 1360 int(obj_hash): [self.deserialize_objectives(obj) for obj in objs] 1361 for obj_hash, objs in inner["objectivesPerPlug"].items() 1362 } 1363 for ins_id, inner in raw_plug_objectives["data"].items() 1364 } 1365 1366 return components.ItemsComponent( 1367 sockets=sockets, 1368 stats=stats, 1369 render_data=render_data, 1370 instances=instances, 1371 objectives=objeectives, 1372 perks=perks, 1373 plug_states=plug_states, 1374 reusable_plugs=reusable_plugs, 1375 plug_objectives=plug_objectives, 1376 )
Deserialize a JSON objects within the itemComponents key.`
1378 def deserialize_character_component( # type: ignore[call-arg] 1379 self, payload: typedefs.JSONObject 1380 ) -> components.CharacterComponent: 1381 character_: typing.Optional[character.Character] = None 1382 if raw_singuler_character := payload.get("character"): 1383 character_ = self.deserialize_character(raw_singuler_character["data"]) 1384 1385 inventory: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None 1386 if raw_inventory := payload.get("inventory"): 1387 if "data" in raw_inventory: 1388 inventory = self.deserialize_profile_items(raw_inventory["data"]) 1389 1390 activities: typing.Optional[activity.CharacterActivity] = None 1391 if raw_activities := payload.get("activities"): 1392 activities = self.deserialize_character_activity(raw_activities["data"]) 1393 1394 equipment: typing.Optional[collections.Sequence[profile.ProfileItemImpl]] = None 1395 if raw_equipments := payload.get("equipment"): 1396 equipment = self.deserialize_profile_items(raw_equipments["data"]) 1397 1398 progressions_: typing.Optional[character.CharacterProgression] = None 1399 if raw_progressions := payload.get("progressions"): 1400 progressions_ = self.deserialize_character_progressions( 1401 raw_progressions["data"] 1402 ) 1403 1404 render_data: typing.Optional[character.RenderedData] = None 1405 if raw_render_data := payload.get("renderData"): 1406 render_data = self.deserialize_character_render_data( 1407 raw_render_data["data"] 1408 ) 1409 1410 character_records: typing.Optional[ 1411 collections.Mapping[int, records.CharacterRecord] 1412 ] = None 1413 if raw_char_records := payload.get("records"): 1414 character_records = self.deserialize_characters_records( 1415 raw_char_records["data"] 1416 ) 1417 1418 item_components: typing.Optional[components.ItemsComponent] = None 1419 if raw_item_components := payload.get("itemComponents"): 1420 item_components = self.deserialize_items_component(raw_item_components) 1421 1422 nodes: typing.Optional[collections.Mapping[int, records.Node]] = None 1423 if raw_nodes := payload.get("presentationNodes"): 1424 nodes = { 1425 int(node_hash): self._deserialize_node(node) 1426 for node_hash, node in raw_nodes["data"]["nodes"].items() 1427 } 1428 1429 collectibles: typing.Optional[items.Collectible] = None 1430 if raw_collectibles := payload.get("collectibles"): 1431 collectibles = self._deserialize_collectible(raw_collectibles["data"]) 1432 1433 currency_lookups: typing.Optional[collections.Sequence[items.Currency]] = None 1434 if raw_currencies := payload.get("currencyLookups"): 1435 if "data" in raw_currencies: 1436 currency_lookups = self._deserialize_currencies(raw_currencies) 1437 1438 return components.CharacterComponent( 1439 activities=activities, 1440 equipment=equipment, 1441 inventory=inventory, 1442 progressions=progressions_, 1443 render_data=render_data, 1444 character=character_, 1445 character_records=character_records, 1446 profile_records=None, 1447 item_components=item_components, 1448 currency_lookups=currency_lookups, 1449 collectibles=collectibles, 1450 nodes=nodes, 1451 )
Deserialize a JSON payload of Destiny 2 character component.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.CharacterComponent: A character component.
1478 def deserialize_inventory_results( 1479 self, payload: typedefs.JSONObject 1480 ) -> iterators.Iterator[entity.SearchableEntity]: 1481 suggested_words: list[str] = payload["suggestedWords"] 1482 1483 def _check_unknown(s: str) -> undefined.UndefinedOr[str]: 1484 return s if not typedefs.is_unknown(s) else undefined.UNDEFINED 1485 1486 return iterators.Iterator( 1487 [ 1488 entity.SearchableEntity( 1489 net=self._net, 1490 hash=data["hash"], 1491 entity_type=data["entityType"], 1492 weight=data["weight"], 1493 suggested_words=suggested_words, 1494 name=data["displayProperties"]["name"], 1495 has_icon=data["displayProperties"]["hasIcon"], 1496 description=_check_unknown( 1497 data["displayProperties"]["description"] 1498 ), 1499 icon=assets.Image(data["displayProperties"]["icon"]), 1500 ) 1501 for data in payload["results"]["results"] 1502 ] 1503 )
Deserialize results of searched Destiny2 entities.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.SearchableEntity]: An iterator over the found searched entities.
1532 def deserialize_inventory_entity( # noqa: C901 Too complex. 1533 self, payload: typedefs.JSONObject, / 1534 ) -> entity.InventoryEntity: 1535 props = self._set_entity_attrs(payload) 1536 objects = self._deserialize_inventory_item_objects(payload) 1537 1538 collectible_hash: typing.Optional[int] = None 1539 if raw_collectible_hash := payload.get("collectibleHash"): 1540 collectible_hash = int(raw_collectible_hash) 1541 1542 secondary_icon: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1543 if raw_second_icon := payload.get("secondaryIcon"): 1544 secondary_icon = assets.Image(raw_second_icon) 1545 1546 secondary_overlay: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1547 if raw_second_overlay := payload.get("secondaryOverlay"): 1548 secondary_overlay = assets.Image(raw_second_overlay) 1549 1550 secondary_special: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1551 if raw_second_special := payload.get("secondarySpecial"): 1552 secondary_special = assets.Image(raw_second_special) 1553 1554 screenshot: undefined.UndefinedOr[assets.Image] = undefined.UNDEFINED 1555 if raw_screenshot := payload.get("screenshot"): 1556 screenshot = assets.Image(raw_screenshot) 1557 1558 watermark_icon: typing.Optional[assets.Image] = None 1559 if raw_watermark_icon := payload.get("iconWatermark"): 1560 watermark_icon = assets.Image(raw_watermark_icon) 1561 1562 watermark_shelved: typing.Optional[assets.Image] = None 1563 if raw_watermark_shelved := payload.get("iconWatermarkShelved"): 1564 watermark_shelved = assets.Image(raw_watermark_shelved) 1565 1566 about: undefined.UndefinedOr[str] = undefined.UNDEFINED 1567 if (raw_about := payload.get("flavorText")) and not typedefs.is_unknown( 1568 raw_about 1569 ): 1570 about = raw_about 1571 1572 ui_item_style: undefined.UndefinedOr[str] = undefined.UNDEFINED 1573 if ( 1574 raw_ui_style := payload.get("uiItemDisplayStyle") 1575 ) and not typedefs.is_unknown(raw_ui_style): 1576 ui_item_style = raw_ui_style 1577 1578 tier_and_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1579 if ( 1580 raw_tier_and_name := payload.get("itemTypeAndTierDisplayName") 1581 ) and not typedefs.is_unknown(raw_tier_and_name): 1582 tier_and_name = raw_tier_and_name 1583 1584 type_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1585 if ( 1586 raw_type_name := payload.get("itemTypeDisplayName") 1587 ) and not typedefs.is_unknown(raw_type_name): 1588 type_name = raw_type_name 1589 1590 display_source: undefined.UndefinedOr[str] = undefined.UNDEFINED 1591 if ( 1592 raw_display_source := payload.get("displaySource") 1593 ) and not typedefs.is_unknown(raw_display_source): 1594 display_source = raw_display_source 1595 1596 lorehash: typing.Optional[int] = None 1597 if raw_lore_hash := payload.get("loreHash"): 1598 lorehash = int(raw_lore_hash) 1599 1600 summary_hash: typing.Optional[int] = None 1601 if raw_summary_hash := payload.get("summaryItemHash"): 1602 summary_hash = raw_summary_hash 1603 1604 breaker_type_hash: typing.Optional[int] = None 1605 if raw_breaker_type_hash := payload.get("breakerTypeHash"): 1606 breaker_type_hash = int(raw_breaker_type_hash) 1607 1608 damage_types: typing.Optional[collections.Sequence[int]] = None 1609 if raw_damage_types := payload.get("damageTypes"): 1610 damage_types = [int(type_) for type_ in raw_damage_types] 1611 1612 damagetype_hashes: typing.Optional[collections.Sequence[int]] = None 1613 if raw_damagetype_hashes := payload.get("damageTypeHashes"): 1614 damagetype_hashes = [int(type_) for type_ in raw_damagetype_hashes] 1615 1616 default_damagetype_hash: typing.Optional[int] = None 1617 if raw_defaultdmg_hash := payload.get("defaultDamageTypeHash"): 1618 default_damagetype_hash = int(raw_defaultdmg_hash) 1619 1620 emblem_objective_hash: typing.Optional[int] = None 1621 if raw_emblem_obj_hash := payload.get("emblemObjectiveHash"): 1622 emblem_objective_hash = int(raw_emblem_obj_hash) 1623 1624 tier_type: typing.Optional[enums.TierType] = None 1625 tier: typing.Optional[enums.ItemTier] = None 1626 bucket_hash: typing.Optional[int] = None 1627 recovery_hash: typing.Optional[int] = None 1628 tier_name: undefined.UndefinedOr[str] = undefined.UNDEFINED 1629 isinstance_item: bool = False 1630 expire_tool_tip: undefined.UndefinedOr[str] = undefined.UNDEFINED 1631 expire_in_orbit_message: undefined.UndefinedOr[str] = undefined.UNDEFINED 1632 suppress_expiration: bool = False 1633 max_stack_size: typing.Optional[int] = None 1634 stack_label: undefined.UndefinedOr[str] = undefined.UNDEFINED 1635 1636 if inventory := payload.get("inventory"): 1637 tier_type = enums.TierType(int(inventory["tierType"])) 1638 tier = enums.ItemTier(int(inventory["tierTypeHash"])) 1639 bucket_hash = int(inventory["bucketTypeHash"]) 1640 recovery_hash = int(inventory["recoveryBucketTypeHash"]) 1641 tier_name = inventory["tierTypeName"] 1642 isinstance_item = inventory["isInstanceItem"] 1643 suppress_expiration = inventory["suppressExpirationWhenObjectivesComplete"] 1644 max_stack_size = int(inventory["maxStackSize"]) 1645 1646 try: 1647 stack_label = inventory["stackUniqueLabel"] 1648 except KeyError: 1649 pass 1650 1651 return entity.InventoryEntity( 1652 net=self._net, 1653 collectible_hash=collectible_hash, 1654 name=props.name, 1655 about=about, 1656 emblem_objective_hash=emblem_objective_hash, 1657 suppress_expiration=suppress_expiration, 1658 max_stack_size=max_stack_size, 1659 stack_label=stack_label, 1660 tier=tier, 1661 tier_type=tier_type, 1662 tier_name=tier_name, 1663 bucket_hash=bucket_hash, 1664 recovery_bucket_hash=recovery_hash, 1665 isinstance_item=isinstance_item, 1666 expire_in_orbit_message=expire_in_orbit_message, 1667 expiration_tooltip=expire_tool_tip, 1668 lore_hash=lorehash, 1669 type_and_tier_name=tier_and_name, 1670 summary_hash=summary_hash, 1671 ui_display_style=ui_item_style, 1672 type_name=type_name, 1673 breaker_type_hash=breaker_type_hash, 1674 description=props.description, 1675 display_source=display_source, 1676 hash=props.hash, 1677 damage_types=damage_types, 1678 index=props.index, 1679 icon=props.icon, 1680 has_icon=props.has_icon, 1681 screenshot=screenshot, 1682 watermark_icon=watermark_icon, 1683 watermark_shelved=watermark_shelved, 1684 secondary_icon=secondary_icon, 1685 secondary_overlay=secondary_overlay, 1686 secondary_special=secondary_special, 1687 type=enums.ItemType(int(payload["itemType"])), 1688 trait_hashes=[int(id_) for id_ in payload.get("traitHashes", [])], 1689 trait_ids=[trait for trait in payload.get("traitIds", [])], 1690 category_hashes=[int(hash_) for hash_ in payload["itemCategoryHashes"]], 1691 item_class=enums.Class(int(payload["classType"])), 1692 sub_type=enums.ItemSubType(int(payload["itemSubType"])), 1693 breaker_type=int(payload["breakerType"]), 1694 default_damagetype=int(payload["defaultDamageType"]), 1695 default_damagetype_hash=default_damagetype_hash, 1696 damagetype_hashes=damagetype_hashes, 1697 tooltip_notifications=payload["tooltipNotifications"], 1698 not_transferable=payload["nonTransferrable"], 1699 allow_actions=payload["allowActions"], 1700 is_equippable=payload["equippable"], 1701 objects=objects, 1702 background_colors=payload.get("backgroundColor", {}), 1703 season_hash=payload.get("seasonHash"), 1704 has_postmaster_effect=payload["doesPostmasterPullHaveSideEffects"], 1705 )
Deserialize a JSON payload of an inventory entity item information.
This can be any item from DestinyInventoryItemDefinition definition.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.InventoryEntity: An entity item.
1707 def deserialize_objective_entity( 1708 self, payload: typedefs.JSONObject, / 1709 ) -> entity.ObjectiveEntity: 1710 props = self._set_entity_attrs(payload) 1711 return entity.ObjectiveEntity( 1712 net=self._net, 1713 hash=props.hash, 1714 index=props.index, 1715 description=props.description, 1716 name=props.name, 1717 has_icon=props.has_icon, 1718 icon=props.icon, 1719 unlock_value_hash=payload["unlockValueHash"], 1720 completion_value=payload["completionValue"], 1721 scope=entity.GatingScope(int(payload["scope"])), 1722 location_hash=payload["locationHash"], 1723 allowed_negative_value=payload["allowNegativeValue"], 1724 allowed_value_change=payload["allowValueChangeWhenCompleted"], 1725 counting_downward=payload["isCountingDownward"], 1726 value_style=entity.ValueUIStyle(int(payload["valueStyle"])), 1727 progress_description=payload["progressDescription"], 1728 perks=payload["perks"], 1729 stats=payload["stats"], 1730 minimum_visibility=payload["minimumVisibilityThreshold"], 1731 allow_over_completion=payload["allowOvercompletion"], 1732 show_value_style=payload["showValueOnComplete"], 1733 display_only_objective=payload["isDisplayOnlyObjective"], 1734 complete_value_style=entity.ValueUIStyle( 1735 int(payload["completedValueStyle"]) 1736 ), 1737 progress_value_style=entity.ValueUIStyle( 1738 int(payload["inProgressValueStyle"]) 1739 ), 1740 ui_label=payload["uiLabel"], 1741 ui_style=entity.ObjectiveUIStyle(int(payload["uiStyle"])), 1742 )
Deserialize a JSON payload of an objective entity information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.ObjectiveEntity: An objective entity.
1770 def deserialize_activity( 1771 self, 1772 payload: typedefs.JSONObject, 1773 /, 1774 ) -> activity.Activity: 1775 period = time.clean_date(payload["period"]) 1776 details = payload["activityDetails"] 1777 ref_id = int(details["referenceId"]) 1778 instance_id = int(details["instanceId"]) 1779 mode = enums.GameMode(details["mode"]) 1780 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] 1781 is_private = details["isPrivate"] 1782 membership_type = enums.MembershipType(int(details["membershipType"])) 1783 1784 # Since we're using the same fields for post activity method 1785 # this check is required since post activity doesn't values values 1786 values = self._deserialize_activity_values(payload["values"]) 1787 1788 return activity.Activity( 1789 net=self._net, 1790 hash=ref_id, 1791 instance_id=instance_id, 1792 mode=mode, 1793 modes=modes, 1794 is_private=is_private, 1795 membership_type=membership_type, 1796 occurred_at=period, 1797 values=values, 1798 )
Deserialize a JSON payload of an activity history information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.Activity: An activity.
1800 def deserialize_activities( 1801 self, payload: typedefs.JSONObject 1802 ) -> iterators.Iterator[activity.Activity]: 1803 return iterators.Iterator( 1804 [ 1805 self.deserialize_activity(activity_) 1806 for activity_ in payload["activities"] 1807 ] 1808 )
Deserialize a JSON payload of an array of activity history information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.Activity]: Am iterator over activity objects of the deserialized payload.
1810 def deserialize_extended_weapon_values( 1811 self, payload: typedefs.JSONObject 1812 ) -> activity.ExtendedWeaponValues: 1813 assists: typing.Optional[int] = None 1814 if raw_assists := payload["values"].get("uniqueWeaponAssists"): 1815 assists = raw_assists["basic"]["value"] 1816 assists_damage: typing.Optional[int] = None 1817 1818 if raw_assists_damage := payload["values"].get("uniqueWeaponAssistDamage"): 1819 assists_damage = raw_assists_damage["basic"]["value"] 1820 1821 return activity.ExtendedWeaponValues( 1822 reference_id=int(payload["referenceId"]), 1823 kills=payload["values"]["uniqueWeaponKills"]["basic"]["value"], 1824 precision_kills=payload["values"]["uniqueWeaponPrecisionKills"]["basic"][ 1825 "value" 1826 ], 1827 assists=assists, 1828 assists_damage=assists_damage, 1829 precision_kills_percentage=( 1830 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"]["value"], 1831 payload["values"]["uniqueWeaponKillsPrecisionKills"]["basic"][ 1832 "displayValue" 1833 ], 1834 ), 1835 )
Deserialize values of extended weapons JSON object.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.ExtendedWeaponValues: Information about an extended weapon values.
1858 def deserialize_post_activity_player( 1859 self, payload: typedefs.JSONObject, / 1860 ) -> activity.PostActivityPlayer: 1861 player = payload["player"] 1862 1863 class_hash: typedefs.NoneOr[int] = None 1864 if (class_hash := player.get("classHash")) is not None: 1865 class_hash = class_hash 1866 1867 race_hash: typedefs.NoneOr[int] = None 1868 if (race_hash := player.get("raceHash")) is not None: 1869 race_hash = race_hash 1870 1871 gender_hash: typedefs.NoneOr[int] = None 1872 if (gender_hash := player.get("genderHash")) is not None: 1873 gender_hash = gender_hash 1874 1875 character_class: undefined.UndefinedOr[str] = undefined.UNDEFINED 1876 if ( 1877 character_class := player.get("characterClass") 1878 ) and not typedefs.is_unknown(character_class): 1879 character_class = character_class 1880 1881 character_level: typedefs.NoneOr[int] = None 1882 if (character_level := player.get("characterLevel")) is not None: 1883 character_level = character_level 1884 1885 return activity.PostActivityPlayer( 1886 standing=int(payload["standing"]), 1887 score=int(payload["score"]["basic"]["value"]), 1888 character_id=payload["characterId"], 1889 destiny_user=self.deserialize_destiny_membership(player["destinyUserInfo"]), 1890 character_class=character_class, 1891 character_level=character_level, 1892 race_hash=race_hash, 1893 gender_hash=gender_hash, 1894 class_hash=class_hash, 1895 light_level=int(player["lightLevel"]), 1896 emblem_hash=int(player["emblemHash"]), 1897 values=self._deserialize_activity_values(payload["values"]), 1898 extended_values=self._deserialize_extended_values(payload["extended"]), 1899 )
Deserialize a JSON payload of a post activity player information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.PostActivityPlayer: A post activity player object.
1911 def deserialize_post_activity( 1912 self, payload: typedefs.JSONObject 1913 ) -> activity.PostActivity: 1914 period = time.clean_date(payload["period"]) 1915 details = payload["activityDetails"] 1916 ref_id = int(details["referenceId"]) 1917 instance_id = int(details["instanceId"]) 1918 mode = enums.GameMode(details["mode"]) 1919 modes = [enums.GameMode(int(mode_)) for mode_ in details["modes"]] 1920 is_private = details["isPrivate"] 1921 membership_type = enums.MembershipType(int(details["membershipType"])) 1922 return activity.PostActivity( 1923 net=self._net, 1924 hash=ref_id, 1925 membership_type=membership_type, 1926 instance_id=instance_id, 1927 mode=mode, 1928 modes=modes, 1929 is_private=is_private, 1930 occurred_at=period, 1931 starting_phase=int(payload["startingPhaseIndex"]), 1932 players=[ 1933 self.deserialize_post_activity_player(player) 1934 for player in payload["entries"] 1935 ], 1936 teams=[ 1937 self._deserialize_post_activity_team(team) for team in payload["teams"] 1938 ], 1939 )
Deserialize a JSON payload of a post activity information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.PostActivity: A post activity object.
1977 def deserialize_aggregated_activity( 1978 self, payload: typedefs.JSONObject 1979 ) -> activity.AggregatedActivity: 1980 return activity.AggregatedActivity( 1981 hash=int(payload["activityHash"]), 1982 values=self._deserialize_aggregated_activity_values(payload["values"]), 1983 )
Deserialize a JSON payload of an aggregated activity.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.AggregatedActivity: An aggregated activity object.
1985 def deserialize_aggregated_activities( 1986 self, payload: typedefs.JSONObject 1987 ) -> iterators.Iterator[activity.AggregatedActivity]: 1988 return iterators.Iterator( 1989 [ 1990 self.deserialize_aggregated_activity(activity) 1991 for activity in payload["activities"] 1992 ] 1993 )
Deserialize a JSON payload of an array of aggregated activities.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.iterators.Iterator[aiobungie.crates.AggregatedActivity]: An iterator over aggregated activities objects.
1995 def deserialize_linked_profiles( 1996 self, payload: typedefs.JSONObject 1997 ) -> profile.LinkedProfile: 1998 bungie_user = self.deserialize_partial_bungie_user(payload["bnetMembership"]) 1999 error_profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] 2000 profiles_vec: typing.MutableSequence[user.DestinyMembership] = [] 2001 2002 if raw_profile := payload.get("profiles"): 2003 for pfile in raw_profile: 2004 profiles_vec.append(self.deserialize_destiny_membership(pfile)) 2005 2006 if raw_profiles_with_errors := payload.get("profilesWithErrors"): 2007 for raw_error_pfile in raw_profiles_with_errors: 2008 if error_pfile := raw_error_pfile.get("infoCard"): 2009 error_profiles_vec.append( 2010 self.deserialize_destiny_membership(error_pfile) 2011 ) 2012 2013 return profile.LinkedProfile( 2014 net=self._net, 2015 bungie=bungie_user, 2016 profiles=profiles_vec, 2017 profiles_with_errors=error_profiles_vec, 2018 )
Deserialize a JSON payload of Bungie.net hard linked profile information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.LinkedProfile: A hard linked profile.
2034 def deserialize_public_milestone_content( 2035 self, payload: typedefs.JSONObject 2036 ) -> milestones.MilestoneContent: 2037 items_categoris: typedefs.NoneOr[milestones.MilestoneItems] = None 2038 if raw_categories := payload.get("itemCategories"): 2039 for item in raw_categories: 2040 title = undefined.UNDEFINED 2041 if raw_title := item.get("title"): 2042 if raw_title != typedefs.Unknown: 2043 title = raw_title 2044 if raw_hashes := item.get("itemHashes"): 2045 hashes: collections.Sequence[int] = raw_hashes 2046 2047 items_categoris = milestones.MilestoneItems(title=title, hashes=hashes) 2048 2049 about = undefined.UNDEFINED 2050 if (raw_about := payload["about"]) != typedefs.Unknown: 2051 about = raw_about 2052 2053 status = undefined.UNDEFINED 2054 if (raw_status := payload["status"]) != typedefs.Unknown: 2055 status = raw_status 2056 2057 tips: typing.MutableSequence[undefined.UndefinedOr[str]] = [] 2058 if raw_tips := payload.get("tips"): 2059 for raw_tip in raw_tips: 2060 if raw_tip == typedefs.Unknown: 2061 raw_tip = undefined.UNDEFINED 2062 tips.append(raw_tip) 2063 2064 return milestones.MilestoneContent( 2065 about=about, status=status, tips=tips, items=items_categoris 2066 )
Deserialize a JSON payload of milestone content information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.MilestoneContent: A milestone content.
2068 def deserialize_friend(self, payload: typedefs.JSONObject, /) -> friends.Friend: 2069 name = undefined.UNDEFINED 2070 if (raw_name := payload["bungieGlobalDisplayName"]) != typedefs.Unknown: 2071 name = raw_name 2072 2073 bungie_user: typedefs.NoneOr[user.BungieUser] = None 2074 2075 if raw_bungie_user := payload.get("bungieNetUser"): 2076 bungie_user = self.deserialize_bungie_user(raw_bungie_user) 2077 2078 return friends.Friend( 2079 net=self._net, 2080 id=int(payload["lastSeenAsMembershipId"]), 2081 name=name, 2082 code=payload.get("bungieGlobalDisplayNameCode"), 2083 relationship=enums.Relationship(payload["relationship"]), 2084 user=bungie_user, 2085 online_status=enums.Presence(payload["onlineStatus"]), 2086 online_title=payload["onlineTitle"], 2087 type=enums.MembershipType(payload["lastSeenAsBungieMembershipType"]), 2088 )
Deserialize a JSON payload of a Bungie friend information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.Friend: A friend.
2090 def deserialize_friends( 2091 self, payload: typedefs.JSONObject 2092 ) -> collections.Sequence[friends.Friend]: 2093 mut_seq: typing.MutableSequence[friends.Friend] = [] 2094 if raw_friends := payload.get("friends"): 2095 for friend in raw_friends: 2096 mut_seq.append(self.deserialize_friend(friend)) 2097 return mut_seq
Deserialize a JSON sequence of Bungie friends information.
This is usually used to deserialize the incoming/outgoing friend requests.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.Friend]: A sequence of friends.
2099 def deserialize_friend_requests( 2100 self, payload: typedefs.JSONObject 2101 ) -> friends.FriendRequestView: 2102 incoming: typing.MutableSequence[friends.Friend] = [] 2103 outgoing: typing.MutableSequence[friends.Friend] = [] 2104 2105 if raw_incoming_requests := payload.get("incomingRequests"): 2106 for incoming_request in raw_incoming_requests: 2107 incoming.append(self.deserialize_friend(incoming_request)) 2108 2109 if raw_outgoing_requests := payload.get("outgoingRequests"): 2110 for outgoing_request in raw_outgoing_requests: 2111 outgoing.append(self.deserialize_friend(outgoing_request)) 2112 2113 return friends.FriendRequestView(incoming=incoming, outgoing=outgoing)
Deserialize a JSON sequence of Bungie friend requests information.
This is used for incoming/outgoing friend requests.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.FriendRequestView]: A sequence of incoming and outgoing friends.
2138 def deserialize_fireteams( 2139 self, payload: typedefs.JSONObject 2140 ) -> typedefs.NoneOr[collections.Sequence[fireteams.Fireteam]]: 2141 fireteams_: typing.MutableSequence[fireteams.Fireteam] = [] 2142 2143 result: list[typedefs.JSONObject] 2144 if not (result := payload["results"]): 2145 return None 2146 for elem in result: 2147 fireteams_.append( 2148 self._set_fireteam_fields( 2149 elem, total_results=int(payload["totalResults"]) 2150 ) 2151 ) 2152 return fireteams_
Deserialize a JSON sequence of Bungie fireteams information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
collections.Sequence[aiobungie.crates.Fireteam]: A sequence of fireteam.
2154 def deserialize_fireteam_destiny_users( 2155 self, payload: typedefs.JSONObject 2156 ) -> fireteams.FireteamUser: 2157 destiny_obj = self.deserialize_destiny_membership(payload) 2158 # We could helpers.just return a DestinyMembership object but this is 2159 # missing the fireteam display name and id fields. 2160 return fireteams.FireteamUser( 2161 net=self._net, 2162 id=destiny_obj.id, 2163 code=destiny_obj.code, 2164 icon=destiny_obj.icon, 2165 types=destiny_obj.types, 2166 type=destiny_obj.type, 2167 is_public=destiny_obj.is_public, 2168 crossave_override=destiny_obj.crossave_override, 2169 name=destiny_obj.name, 2170 last_seen_name=destiny_obj.last_seen_name, 2171 fireteam_display_name=payload["FireteamDisplayName"], 2172 fireteam_membership_id=enums.MembershipType( 2173 payload["FireteamMembershipType"] 2174 ), 2175 )
Deserialize a JSON payload of Bungie fireteam destiny users information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.FireteamUser: A fireteam user.
2177 def deserialize_fireteam_members( 2178 self, payload: typedefs.JSONObject, *, alternatives: bool = False 2179 ) -> typing.Optional[collections.Sequence[fireteams.FireteamMember]]: 2180 members_: list[fireteams.FireteamMember] = [] 2181 if members := payload.get("Members" if not alternatives else "Alternates"): 2182 for member in members: 2183 bungie_fields = self.deserialize_partial_bungie_user(member) 2184 members_fields = fireteams.FireteamMember( 2185 destiny_user=self.deserialize_fireteam_destiny_users(member), 2186 has_microphone=member["hasMicrophone"], 2187 character_id=int(member["characterId"]), 2188 date_joined=time.clean_date(member["dateJoined"]), 2189 last_platform_invite_date=time.clean_date( 2190 member["lastPlatformInviteAttemptDate"] 2191 ), 2192 last_platform_invite_result=int( 2193 member["lastPlatformInviteAttemptResult"] 2194 ), 2195 net=self._net, 2196 name=bungie_fields.name, 2197 id=bungie_fields.id, 2198 icon=bungie_fields.icon, 2199 is_public=bungie_fields.is_public, 2200 crossave_override=bungie_fields.crossave_override, 2201 types=bungie_fields.types, 2202 type=bungie_fields.type, 2203 ) 2204 members_.append(members_fields) 2205 else: 2206 return None 2207 return members_
Deserialize a JSON sequence of Bungie fireteam members information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload. - alternatives (
bool): If set toTrue, Then it will deserialize thealternativesdata in the payload. If not the it will just deserialize themembersdata.
Returns
typing.Optional[collections.Sequence[aiobungie.crates.FireteamUser]]: An optional sequence of the fireteam members.
2209 def deserialize_available_fireteams( 2210 self, 2211 data: typedefs.JSONObject, 2212 *, 2213 no_results: bool = False, 2214 ) -> typing.Union[ 2215 fireteams.AvailableFireteam, collections.Sequence[fireteams.AvailableFireteam] 2216 ]: 2217 fireteams_: list[fireteams.AvailableFireteam] = [] 2218 2219 # This needs to be used outside the results 2220 # JSON key. 2221 if no_results is True: 2222 payload = data 2223 2224 if result := payload.get("results"): 2225 for fireteam in result: 2226 found_fireteams = self._set_fireteam_fields(fireteam["Summary"]) 2227 fireteams_fields = fireteams.AvailableFireteam( 2228 id=found_fireteams.id, 2229 group_id=found_fireteams.group_id, 2230 platform=found_fireteams.platform, 2231 activity_type=found_fireteams.activity_type, 2232 is_immediate=found_fireteams.is_immediate, 2233 is_public=found_fireteams.is_public, 2234 is_valid=found_fireteams.is_valid, 2235 owner_id=found_fireteams.owner_id, 2236 player_slot_count=found_fireteams.player_slot_count, 2237 available_player_slots=found_fireteams.available_player_slots, 2238 available_alternate_slots=found_fireteams.available_alternate_slots, 2239 title=found_fireteams.title, 2240 date_created=found_fireteams.date_created, 2241 locale=found_fireteams.locale, 2242 last_modified=found_fireteams.last_modified, 2243 total_results=found_fireteams.total_results, 2244 members=self.deserialize_fireteam_members(payload), 2245 alternatives=self.deserialize_fireteam_members( 2246 payload, alternatives=True 2247 ), 2248 ) 2249 fireteams_.append(fireteams_fields) 2250 if no_results: 2251 return fireteams_fields 2252 return fireteams_
Deserialize a JSON payload of a sequence of/fireteam information.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload. - no_results (
bool): Whether to deserialize the data fromresultsin the payload or not.
Returns
typing.Union[aiobungie.crates.fireteams.AvailableFireteam, collections.Sequence[aiobungie.crates.fireteams.AvailableFireteam]]# noqa (E501): An available fireteam or a sequence of available fireteam.
2254 def deserialize_fireteam_party( 2255 self, payload: typedefs.JSONObject 2256 ) -> fireteams.FireteamParty: 2257 last_destination_hash: typing.Optional[int] = None 2258 if raw_dest_hash := payload.get("lastOrbitedDestinationHash"): 2259 last_destination_hash = int(raw_dest_hash) 2260 2261 return fireteams.FireteamParty( 2262 members=[ 2263 self._deserialize_fireteam_party_member(member) 2264 for member in payload["partyMembers"] 2265 ], 2266 activity=self._deserialize_fireteam_party_current_activity( 2267 payload["currentActivity"] 2268 ), 2269 settings=self._deserialize_fireteam_party_settings(payload["joinability"]), 2270 last_destination_hash=last_destination_hash, 2271 tracking=payload["tracking"], 2272 )
Deserialize a JSON payload of profileTransitory component response.
Parameters
- payload (
aiobungie.typedefs.JSONObject): The JSON payload.
Returns
aiobungie.crates.FireteamParty: A fireteam party object of the current fireteam.
2318 def deserialize_seasonal_artifact( 2319 self, payload: typedefs.JSONObject 2320 ) -> season.Artifact: 2321 if raw_artifact := payload.get("seasonalArtifact"): 2322 if points := raw_artifact.get("pointProgression"): 2323 points_prog = progressions.Progression( 2324 hash=points["progressionHash"], 2325 level=points["level"], 2326 cap=points["levelCap"], 2327 daily_limit=points["dailyLimit"], 2328 weekly_limit=points["weeklyLimit"], 2329 current_progress=points["currentProgress"], 2330 daily_progress=points["dailyProgress"], 2331 needed=points["progressToNextLevel"], 2332 next_level=points["nextLevelAt"], 2333 ) 2334 2335 if bonus := raw_artifact.get("powerBonusProgression"): 2336 power_bonus_prog = progressions.Progression( 2337 hash=bonus["progressionHash"], 2338 level=bonus["level"], 2339 cap=bonus["levelCap"], 2340 daily_limit=bonus["dailyLimit"], 2341 weekly_limit=bonus["weeklyLimit"], 2342 current_progress=bonus["currentProgress"], 2343 daily_progress=bonus["dailyProgress"], 2344 needed=bonus["progressToNextLevel"], 2345 next_level=bonus["nextLevelAt"], 2346 ) 2347 artifact = season.Artifact( 2348 net=self._net, 2349 hash=raw_artifact["artifactHash"], 2350 power_bonus=raw_artifact["powerBonus"], 2351 acquired_points=raw_artifact["pointsAcquired"], 2352 bonus=power_bonus_prog, 2353 points=points_prog, 2354 ) 2355 return artifact
Deserialize a JSON payload of a Destiny 2 seasonal artifact information.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.Artifact: A seasonal artifact.
2357 def deserialize_profile_progression( 2358 self, payload: typedefs.JSONObject 2359 ) -> profile.ProfileProgression: 2360 return profile.ProfileProgression( 2361 artifact=self.deserialize_seasonal_artifact(payload["data"]), 2362 checklist={ 2363 int(check_id): checklists 2364 for check_id, checklists in payload["data"]["checklists"].items() 2365 }, 2366 )
Deserialize a JSON payload of a profile progression component.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.ProfileProgression: A profile progression component.
2368 def deserialize_instanced_item( 2369 self, payload: typedefs.JSONObject 2370 ) -> items.ItemInstance: 2371 damage_type_hash: typing.Optional[int] = None 2372 if raw_damagetype_hash := payload.get("damageTypeHash"): 2373 damage_type_hash = int(raw_damagetype_hash) 2374 2375 required_hashes: typing.Optional[collections.Collection[int]] = None 2376 if raw_required_hashes := payload.get("unlockHashesRequiredToEquip"): 2377 required_hashes = [int(raw_hash) for raw_hash in raw_required_hashes] 2378 2379 breaker_type: typing.Optional[items.ItemBreakerType] = None 2380 if raw_break_type := payload.get("breakerType"): 2381 breaker_type = items.ItemBreakerType(int(raw_break_type)) 2382 2383 breaker_type_hash: typing.Optional[int] = None 2384 if raw_break_type_hash := payload.get("breakerTypeHash"): 2385 breaker_type_hash = int(raw_break_type_hash) 2386 2387 energy: typing.Optional[items.ItemEnergy] = None 2388 if raw_energy := payload.get("energy"): 2389 energy = self.deserialize_item_energy(raw_energy) 2390 2391 primary_stats = None 2392 if raw_primary_stats := payload.get("primaryStat"): 2393 primary_stats = self.deserialize_item_stats_view(raw_primary_stats) 2394 2395 return items.ItemInstance( 2396 damage_type=enums.DamageType(int(payload["damageType"])), 2397 damage_type_hash=damage_type_hash, 2398 primary_stat=primary_stats, 2399 item_level=int(payload["itemLevel"]), 2400 quality=int(payload["quality"]), 2401 is_equipped=payload["isEquipped"], 2402 can_equip=payload["canEquip"], 2403 equip_required_level=int(payload["equipRequiredLevel"]), 2404 required_equip_unlock_hashes=required_hashes, 2405 cant_equip_reason=int(payload["cannotEquipReason"]), 2406 breaker_type=breaker_type, 2407 breaker_type_hash=breaker_type_hash, 2408 energy=energy, 2409 )
Deserialize a JSON object into an instanced item.
Parameters
- payload (
aiobungie.internal.helpers.JsonObject): The JSON payload.
Returns
aiobungie.crates.ItemInstance: An instanced item object.
2411 def deserialize_item_energy(self, payload: typedefs.JSONObject) -> items.ItemEnergy: 2412 energy_hash: typing.Optional[int] = None 2413 if raw_energy_hash := payload.get("energyTypeHash"): 2414 energy_hash = int(raw_energy_hash) 2415 2416 return items.ItemEnergy( 2417 hash=energy_hash, 2418 type=items.ItemEnergyType(int(payload["energyType"])), 2419 capacity=int(payload["energyCapacity"]), 2420 used_energy=int(payload["energyUsed"]), 2421 unused_energy=int(payload["energyUnused"]), 2422 )
2424 def deserialize_item_perk(self, payload: typedefs.JSONObject) -> items.ItemPerk: 2425 perk_hash: typing.Optional[int] = None 2426 if raw_perk_hash := payload.get("perkHash"): 2427 perk_hash = int(raw_perk_hash) 2428 2429 return items.ItemPerk( 2430 hash=perk_hash, 2431 icon=assets.Image(payload["iconPath"]), 2432 is_active=payload["isActive"], 2433 is_visible=payload["visible"], 2434 )
2436 def deserialize_item_socket(self, payload: typedefs.JSONObject) -> items.ItemSocket: 2437 plug_hash: typing.Optional[int] = None 2438 if raw_plug_hash := payload.get("plugHash"): 2439 plug_hash = int(raw_plug_hash) 2440 2441 enable_fail_indexes: typing.Optional[list[int]] = None 2442 if raw_indexes := payload.get("enableFailIndexes"): 2443 enable_fail_indexes = [int(index) for index in raw_indexes] 2444 2445 return items.ItemSocket( 2446 plug_hash=plug_hash, 2447 is_enabled=payload["isEnabled"], 2448 enable_fail_indexes=enable_fail_indexes, 2449 is_visible=payload.get("visible"), 2450 )
2459 def deserialize_plug_item_state( 2460 self, payload: typedefs.JSONObject 2461 ) -> items.PlugItemState: 2462 item_hash: typing.Optional[int] = None 2463 if raw_item_hash := payload.get("plugItemHash"): 2464 item_hash = int(raw_item_hash) 2465 2466 insert_fail_indexes: typedefs.NoneOr[list[int]] = None 2467 if raw_fail_indexes := payload.get("insertFailIndexes"): 2468 insert_fail_indexes = [int(k) for k in raw_fail_indexes] 2469 2470 enable_fail_indexes: typedefs.NoneOr[list[int]] = None 2471 if raw_enabled_indexes := payload.get("enableFailIndexes"): 2472 enable_fail_indexes = [int(k) for k in raw_enabled_indexes] 2473 2474 return items.PlugItemState( 2475 item_hash=item_hash, 2476 insert_fail_indexes=insert_fail_indexes, 2477 enable_fail_indexes=enable_fail_indexes, 2478 is_enabled=payload["enabled"], 2479 can_insert=payload["canInsert"], 2480 )
67@typing.final 68class FireteamActivity(int, enums.Enum): 69 """An enum for the fireteam activities.""" 70 71 ALL = 0 72 CRUCIBLE = 2 73 TRIALS_OF_OSIRIS = 3 74 NIGHTFALL = 4 75 ANY = 5 76 GAMBIT = 6 77 BLIND_WELL = 7 78 NIGHTMARE_HUNTS = 12 79 ALTARS_OF_SORROWS = 14 80 DUNGEON = 15 81 RAID_LW = 20 82 RAID_GOS = 21 83 RAID_DSC = 22 84 EXO_CHALLENGE = 23 85 S12_WRATHBORN = 24 86 EMPIRE_HUNTS = 25 87 S13_BATTLEGROUNDS = 26 88 EXOTIC_QUEST = 27 89 RAID_VOG = 28 90 S14_EXPUNGE = 30 91 S15_ASTRAL_ALIGNMENT = 31 92 S15_SHATTERED_RELAM = 32 93 SHATTERED_THRONE = 33 94 PROPHECY = 34 95 PIT_OF_HERESY = 35 96 DOE = 36 97 """Dares of Eternity.""" 98 DUNGEON_GOA = 37 99 """Grasp of Avarice.""" 100 VOW_OF_THE_DISCPILE = 38 101 CAMPAIGN = 39 102 WELLSPRING = 40 103 S16_BATTLEGROUNDS = 41 104 S17_NIGHTMARE_CONTAINMENT = 44 105 S17_SEVER = 45
An enum for the fireteam activities.
131@typing.final 132class FireteamDate(int, enums.Enum): 133 """An enum for fireteam date ranges.""" 134 135 ALL = 0 136 NOW = 1 137 TODAY = 2 138 TWO_DAYS = 3 139 THIS_WEEK = 4
An enum for fireteam date ranges.
108@typing.final 109class FireteamLanguage(str, enums.Enum): 110 """An enum for fireteams languages filters.""" 111 112 ALL = "" 113 ENGLISH = "en" 114 FRENCH = "fr" 115 ESPANOL = "es" 116 DEUTSCH = "de" 117 ITALIAN = "it" 118 JAPANESE = "ja" 119 PORTUGUESE = "pt-br" 120 RUSSIAN = "ru" 121 POLISH = "pl" 122 KOREAN = "ko" 123 # ? China 124 ZH_CHT = "zh-cht" 125 ZH_CHS = "zh-chs" 126 127 def __str__(self) -> str: 128 return str(self.value)
An enum for fireteams languages filters.
Inherited Members
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
54@typing.final 55class FireteamPlatform(int, enums.Enum): 56 """An enum for fireteam related to bungie fireteams. 57 This is different from the normal `aiobungie.MembershipType`. 58 """ 59 60 ANY = 0 61 PSN_NETWORK = 1 62 XBOX_LIVE = 2 63 STEAM = 4 64 STADIA = 5
An enum for fireteam related to bungie fireteams.
This is different from the normal aiobungie.MembershipType.
97class Flag(__enum.Flag): 98 """Builtin Python enum flag with extra handlings.""" 99 100 # Needs to type this here for mypy 101 _value_: int 102 103 @property 104 def name(self) -> str: # type: ignore[override] 105 if self._name_ is None: 106 self._name_ = f"UNKNOWN {self._value_}" 107 108 return self._name_ 109 110 @property 111 def value(self) -> int: # type: ignore[override] 112 return self._value_ 113 114 def __str__(self) -> str: 115 return self.name 116 117 def __repr__(self) -> str: 118 return f"<{type(self).__name__}.{self.name}: {self._value_!s}>" 119 120 def __int__(self) -> int: 121 if isinstance(self.value, _ITERABLE): 122 raise TypeError( 123 f"Can't overload {self.value} in {type(self).__name__}, Please use `.value` attribute.", 124 ) 125 return int(self.value) 126 127 def __or__(self, other: typing.Union[Flag, int]) -> Flag: 128 return self.__class__(self._value_ | int(other)) 129 130 def __xor__(self, other: typing.Union[Flag, int]) -> Flag: 131 return self.__class__(self._value_ ^ int(other)) 132 133 def __and__(self, other: typing.Union[Flag, int]) -> Flag: 134 return self.__class__(other & int(other)) 135 136 def __invert__(self) -> Flag: 137 return self.__class__(~self._value_) 138 139 def __contains__(self, other: typing.Union[Flag, int]) -> bool: 140 return self.value & int(other) == int(other)
Builtin Python enum flag with extra handlings.
137@attrs.define(auto_exc=True) 138class Forbidden(HTTPException): 139 """Exception that's raised for when status code 403 occurs.""" 140 141 http_status: http.HTTPStatus = attrs.field( 142 default=http.HTTPStatus.FORBIDDEN, init=False 143 )
Exception that's raised for when status code 403 occurs.
2def __init__(self, *, error_code, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.throttle_seconds = throttle_seconds 5 self.url = url 6 self.body = body 7 self.headers = headers 8 self.message = message 9 self.error_status = error_status 10 self.message_data = message_data 11 self.http_status = attr_dict['http_status'].default 12 BaseException.__init__(self, self.error_code,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class Forbidden.
Inherited Members
- builtins.BaseException
- with_traceback
- args
269@typing.final 270class GameMode(int, Enum): 271 """An Enum for all available gamemodes in Destiny 2.""" 272 273 NONE = 0 274 STORY = 2 275 STRIKE = 3 276 RAID = 4 277 ALLPVP = 5 278 PATROL = 6 279 ALLPVE = 7 280 RESERVED9 = 9 281 CONTROL = 10 282 RESERVED11 = 11 283 CLASH = 12 284 RESERVED13 = 13 285 CRIMSONDOUBLES = 15 286 NIGHTFALL = 16 287 HEROICNIGHTFALL = 17 288 ALLSTRIKES = 18 289 IRONBANNER = 19 290 RESERVED20 = 20 291 RESERVED21 = 21 292 RESERVED22 = 22 293 RESERVED24 = 24 294 ALLMAYHEM = 25 295 RESERVED26 = 26 296 RESERVED27 = 27 297 RESERVED28 = 28 298 RESERVED29 = 29 299 RESERVED30 = 30 300 SUPREMACY = 31 301 PRIVATEMATCHESALL = 32 302 SURVIVAL = 37 303 COUNTDOWN = 38 304 TRIALSOFTHENINE = 39 305 SOCIAL = 40 306 TRIALSCOUNTDOWN = 41 307 TRIALSSURVIVAL = 42 308 IRONBANNERCONTROL = 43 309 IRONBANNERCLASH = 44 310 IRONBANNERSUPREMACY = 45 311 SCOREDNIGHTFALL = 46 312 SCOREDHEROICNIGHTFALL = 47 313 RUMBLE = 48 314 ALLDOUBLES = 49 315 DOUBLES = 50 316 PRIVATEMATCHESCLASH = 51 317 PRIVATEMATCHESCONTROL = 52 318 PRIVATEMATCHESSUPREMACY = 53 319 PRIVATEMATCHESCOUNTDOWN = 54 320 PRIVATEMATCHESSURVIVAL = 55 321 PRIVATEMATCHESMAYHEM = 56 322 PRIVATEMATCHESRUMBLE = 57 323 HEROICADVENTURE = 58 324 SHOWDOWN = 59 325 LOCKDOWN = 60 326 SCORCHED = 61 327 SCORCHEDTEAM = 62 328 GAMBIT = 63 329 ALLPVECOMPETITIVE = 64 330 BREAKTHROUGH = 65 331 BLACKARMORYRUN = 66 332 SALVAGE = 67 333 IRONBANNERSALVAGE = 68 334 PVPCOMPETITIVE = 69 335 PVPQUICKPLAY = 70 336 CLASHQUICKPLAY = 71 337 CLASHCOMPETITIVE = 72 338 CONTROLQUICKPLAY = 73 339 CONTROLCOMPETITIVE = 74 340 GAMBITPRIME = 75 341 RECKONING = 76 342 MENAGERIE = 77 343 VEXOFFENSIVE = 78 344 NIGHTMAREHUNT = 79 345 ELIMINATION = 80 346 MOMENTUM = 81 347 DUNGEON = 82 348 SUNDIAL = 83 349 TRIALS_OF_OSIRIS = 84 350 DARES = 85 351 OFFENSIVE = 86 352 LOSTSECTOR = 87 353 RIFT = 88 354 ZONECONTROL = 89 355 IRONBANNERRIFT = 90
An Enum for all available gamemodes in Destiny 2.
58@typing.final 59class GatingScope(int, enums.Enum): 60 """An enum represents restrictive type of gating that is being performed by an entity. 61 62 This is useful as a shortcut to avoid a lot of lookups when determining whether the gating on an Entity 63 applies to everyone equally, or to their specific Profile or Character states. 64 """ 65 66 NONE = 0 67 GLOBAL = 1 68 CLAN = 2 69 PROFILE = 3 70 CHARACTER = 4 71 ITEM = 5 72 ASSUMED_WORST_CASE = 6
An enum represents restrictive type of gating that is being performed by an entity.
This is useful as a shortcut to avoid a lot of lookups when determining whether the gating on an Entity applies to everyone equally, or to their specific Profile or Character states.
486@typing.final 487class Gender(int, Enum): 488 """An Enum for Destiny Genders.""" 489 490 MALE = 0 491 FEMALE = 1 492 UNKNOWN = 2
An Enum for Destiny Genders.
655@typing.final 656class GroupType(int, Enum): 657 """An enums for the known bungie group types.""" 658 659 GENERAL = 0 660 CLAN = 1
An enums for the known bungie group types.
79@attrs.define(auto_exc=True) 80class HTTPError(AiobungieError): 81 """Base HTTP request errors exception.""" 82 83 message: str 84 """The error message.""" 85 86 http_status: http.HTTPStatus 87 """The response status."""
Base HTTP request errors exception.
2def __init__(self, message, http_status): 3 self.message = message 4 self.http_status = http_status 5 BaseException.__init__(self, self.message,self.http_status)
Method generated by attrs for class HTTPError.
Inherited Members
- builtins.BaseException
- with_traceback
- args
90@attrs.define(auto_exc=True, kw_only=True) 91class HTTPException(HTTPError): 92 """An in-depth HTTP exception that's raised with more information.""" 93 94 error_code: int 95 """The returned Bungie error status code.""" 96 97 http_status: http.HTTPStatus 98 """The request response http status.""" 99 100 throttle_seconds: int 101 """The Bungie response throttle seconds.""" 102 103 url: typing.Optional[typedefs.StrOrURL] 104 """The URL/endpoint caused this error.""" 105 106 body: typing.Any 107 """The response body.""" 108 109 headers: multidict.CIMultiDictProxy[str] 110 """The response headers.""" 111 112 message: str 113 """A Bungie human readable message describes the cause of the error.""" 114 115 error_status: str 116 """A Bungie short error status describes the cause of the error.""" 117 118 message_data: dict[str, str] 119 """A dict of string key, value that includes each cause of the error 120 to a message describes information about that error. 121 """ 122 123 def __str__(self) -> str: 124 if self.message: 125 message_body = self.message 126 127 if self.error_status: 128 error_status_body = self.error_status 129 130 return ( 131 f"{self.http_status.name.replace('_', '').title()} {self.http_status.value}: " 132 f"Error status: {error_status_body}, Error message: {message_body} from {self.url} " 133 f"{str(self.body)}" 134 )
An in-depth HTTP exception that's raised with more information.
2def __init__(self, *, error_code, http_status, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.http_status = http_status 5 self.throttle_seconds = throttle_seconds 6 self.url = url 7 self.body = body 8 self.headers = headers 9 self.message = message 10 self.error_status = error_status 11 self.message_data = message_data 12 BaseException.__init__(self, self.error_code,self.http_status,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class HTTPException.
A dict of string key, value that includes each cause of the error to a message describes information about that error.
Inherited Members
- builtins.BaseException
- with_traceback
- args
71class Image: 72 """Representation of an image/avatar/picture at Bungie. 73 74 Example 75 ------- 76 ```py 77 from aiobungie import Image 78 img = Image("img/destiny_content/pgcr/raid_eclipse.jpg") 79 print(img) 80 # https://www.bungie.net/img/destiny_content/pgcr/raid_eclipse.jpg 81 82 # Stream the image. 83 async for chunk in img: 84 # Byte chunks of the image. 85 print(chunk) 86 87 # Save the image to a file. 88 await img.save("file_name", "/my/path/to/save/to", "jpeg") 89 ``` 90 91 Parameters 92 ---------- 93 path : `str | None` 94 The path to the image. If `None`, the default missing image path will be used. 95 """ 96 97 __slots__ = ("_path",) 98 99 def __init__(self, path: typing.Optional[str] = None) -> None: 100 self._path = path 101 102 @property 103 def is_missing(self) -> bool: 104 return not self._path 105 106 @property 107 def url(self) -> str: 108 """The URL to the image.""" 109 return self.create_url() 110 111 @staticmethod 112 def missing_path() -> str: 113 """Returns the path to the missing Bungie image.""" 114 return "img/misc/missing_icon_d2.png" 115 116 def create_url(self) -> str: 117 """Creates a full URL to the image path. 118 119 Returns 120 ------- 121 str 122 The URL to the image. 123 """ 124 return f"{url.BASE}/{self._path if self._path else self.missing_path()}" 125 126 async def save( 127 self, 128 file_name: str, 129 path: typing.Union[pathlib.Path, str], 130 /, 131 mime_type: typing.Optional[typing.Union[MimeType, str]] = None, 132 ) -> None: 133 """Saves the image to a file. 134 135 Parameters 136 ---------- 137 file_name : `str` 138 A name for the file to save the image to. 139 path : `pathlib.Path | str` 140 A path tp save the image to. 141 142 Other Parameters 143 ---------------- 144 mime_type : `MimeType | str` 145 Optional MIME type of the image. 146 147 Raises 148 ------ 149 `FileNotFoundError` 150 If the path provided does not exist. 151 `RuntimeError` 152 If the image could not be saved. 153 `PermissionError` 154 If the path provided is not writable or does not have write permissions. 155 """ 156 if isinstance(path, pathlib.Path) and not path.exists(): 157 raise FileNotFoundError(f"File does not exist: {path!r}") 158 159 if self.is_missing: 160 return 161 162 mimetype = mime_type or MimeType.PNG 163 path = pathlib.Path(path) 164 165 loop = helpers.get_or_make_loop() 166 pool = concurrent.futures.ThreadPoolExecutor() 167 168 try: 169 with pool: 170 await loop.run_in_executor( 171 pool, _write, path, file_name, mimetype, await self.read() 172 ) 173 _LOGGER.info("Saved image to %s", file_name) 174 175 except asyncio.CancelledError: 176 pass 177 178 except Exception as err: 179 raise RuntimeError("Encountered an error while saving image.") from err 180 181 async def read(self) -> bytes: 182 """Read this image bytes. 183 184 Returns 185 ------- 186 `bytes` 187 The bytes of this image. 188 """ 189 client_session = aiohttp.ClientSession() 190 191 try: 192 await client_session.__aenter__() 193 response = await client_session.get(self.create_url()) 194 195 if 300 >= response.status >= 200: 196 reader = await response.read() 197 198 except Exception as exc: 199 raise RuntimeError(f"Failed to read image: {exc}") from None 200 finally: 201 await client_session.__aexit__(None, None, None) 202 return reader 203 204 async def iter(self) -> collections.AsyncGenerator[bytes, None]: 205 """Iterates over the image bytes lazily. 206 207 Example 208 ------- 209 import aiobungie 210 211 resource = aiobungie.Image("img/misc/missing_icon_d2.png") 212 async for chunk in resource.iter(): 213 print(chunk) 214 215 Returns 216 ------- 217 `collections.AsyncGenerator[bytes, None]` 218 An async generator of the image bytes. 219 """ 220 221 async for chunk in self: 222 yield chunk 223 224 def __repr__(self) -> str: 225 return f"Image(url={self.create_url()})" 226 227 def __str__(self) -> str: 228 return self.create_url() 229 230 def __aiter__(self) -> Image: 231 return self 232 233 async def __anext__(self) -> bytes: 234 return await self.read() 235 236 def __await__(self) -> collections.Generator[None, None, bytes]: 237 return self.__anext__().__await__()
Representation of an image/avatar/picture at Bungie.
Example
from aiobungie import Image
img = Image("img/destiny_content/pgcr/raid_eclipse.jpg")
print(img)
# https://www.bungie.net/img/destiny_content/pgcr/raid_eclipse.jpg
# Stream the image.
async for chunk in img:
# Byte chunks of the image.
print(chunk)
# Save the image to a file.
await img.save("file_name", "/my/path/to/save/to", "jpeg")
Parameters
- path (
str | None): The path to the image. IfNone, the default missing image path will be used.
111 @staticmethod 112 def missing_path() -> str: 113 """Returns the path to the missing Bungie image.""" 114 return "img/misc/missing_icon_d2.png"
Returns the path to the missing Bungie image.
116 def create_url(self) -> str: 117 """Creates a full URL to the image path. 118 119 Returns 120 ------- 121 str 122 The URL to the image. 123 """ 124 return f"{url.BASE}/{self._path if self._path else self.missing_path()}"
Creates a full URL to the image path.
Returns
- str: The URL to the image.
126 async def save( 127 self, 128 file_name: str, 129 path: typing.Union[pathlib.Path, str], 130 /, 131 mime_type: typing.Optional[typing.Union[MimeType, str]] = None, 132 ) -> None: 133 """Saves the image to a file. 134 135 Parameters 136 ---------- 137 file_name : `str` 138 A name for the file to save the image to. 139 path : `pathlib.Path | str` 140 A path tp save the image to. 141 142 Other Parameters 143 ---------------- 144 mime_type : `MimeType | str` 145 Optional MIME type of the image. 146 147 Raises 148 ------ 149 `FileNotFoundError` 150 If the path provided does not exist. 151 `RuntimeError` 152 If the image could not be saved. 153 `PermissionError` 154 If the path provided is not writable or does not have write permissions. 155 """ 156 if isinstance(path, pathlib.Path) and not path.exists(): 157 raise FileNotFoundError(f"File does not exist: {path!r}") 158 159 if self.is_missing: 160 return 161 162 mimetype = mime_type or MimeType.PNG 163 path = pathlib.Path(path) 164 165 loop = helpers.get_or_make_loop() 166 pool = concurrent.futures.ThreadPoolExecutor() 167 168 try: 169 with pool: 170 await loop.run_in_executor( 171 pool, _write, path, file_name, mimetype, await self.read() 172 ) 173 _LOGGER.info("Saved image to %s", file_name) 174 175 except asyncio.CancelledError: 176 pass 177 178 except Exception as err: 179 raise RuntimeError("Encountered an error while saving image.") from err
Saves the image to a file.
Parameters
- file_name (
str): A name for the file to save the image to. - path (
pathlib.Path | str): A path tp save the image to.
Other Parameters
- mime_type (
MimeType | str): Optional MIME type of the image.
Raises
FileNotFoundError: If the path provided does not exist.RuntimeError: If the image could not be saved.PermissionError: If the path provided is not writable or does not have write permissions.
181 async def read(self) -> bytes: 182 """Read this image bytes. 183 184 Returns 185 ------- 186 `bytes` 187 The bytes of this image. 188 """ 189 client_session = aiohttp.ClientSession() 190 191 try: 192 await client_session.__aenter__() 193 response = await client_session.get(self.create_url()) 194 195 if 300 >= response.status >= 200: 196 reader = await response.read() 197 198 except Exception as exc: 199 raise RuntimeError(f"Failed to read image: {exc}") from None 200 finally: 201 await client_session.__aexit__(None, None, None) 202 return reader
Read this image bytes.
Returns
bytes: The bytes of this image.
204 async def iter(self) -> collections.AsyncGenerator[bytes, None]: 205 """Iterates over the image bytes lazily. 206 207 Example 208 ------- 209 import aiobungie 210 211 resource = aiobungie.Image("img/misc/missing_icon_d2.png") 212 async for chunk in resource.iter(): 213 print(chunk) 214 215 Returns 216 ------- 217 `collections.AsyncGenerator[bytes, None]` 218 An async generator of the image bytes. 219 """ 220 221 async for chunk in self: 222 yield chunk
Iterates over the image bytes lazily.
Example
import aiobungie
resource = aiobungie.Image("img/misc/missing_icon_d2.png") async for chunk in resource.iter(): print(chunk)
Returns
collections.AsyncGenerator[bytes, None]: An async generator of the image bytes.
243@attrs.define(auto_exc=True) 244class InternalServerError(HTTPException): 245 """Raised for 5xx internal server errors."""
Raised for 5xx internal server errors.
2def __init__(self, *, error_code, http_status, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.http_status = http_status 5 self.throttle_seconds = throttle_seconds 6 self.url = url 7 self.body = body 8 self.headers = headers 9 self.message = message 10 self.error_status = error_status 11 self.message_data = message_data 12 BaseException.__init__(self, self.error_code,self.http_status,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class InternalServerError.
Inherited Members
- HTTPException
- error_code
- http_status
- throttle_seconds
- url
- body
- headers
- message
- error_status
- message_data
- builtins.BaseException
- with_traceback
- args
721@typing.final 722class ItemBindStatus(int, Enum): 723 """An enum for Destiny 2 items bind status.""" 724 725 NOT_BOUND = 0 726 BOUND_TO_CHARACTER = 1 727 BOUND_TO_ACCOUNT = 2 728 BOUNT_TO_GUILD = 3
An enum for Destiny 2 items bind status.
731@typing.final 732class ItemLocation(int, Enum): 733 """An enum for Destiny 2 items location.""" 734 735 UNKNOWN = 0 736 INVENTORY = 1 737 VAULT = 2 738 VENDOR = 3 739 POSTMASTER = 4
An enum for Destiny 2 items location.
756@typing.final 757class ItemState(Flag): 758 """An enum for Destiny 2 item states.""" 759 760 NONE = 0 761 LOCKED = 1 << 0 762 TRACKED = 1 << 1 763 MASTERWORKED = 1 << 2 764 CRAFTED = 1 << 3 765 """If this bit is set, the item has been 'crafted' by the player.""" 766 HIGHLITED_OBJECTIVE = 1 << 4 767 """If this bit is set, the item is a 'highlighted' objective."""
An enum for Destiny 2 item states.
If this bit is set, the item is a 'highlighted' objective.
588@typing.final 589class ItemSubType(int, Enum): 590 """An enum for Destiny 2 inventory items subtype.""" 591 592 NONE = 0 593 AUTORIFLE = 6 594 SHOTGUN = 7 595 MACHINEGUN = 8 596 HANDCANNON = 9 597 ROCKETLAUNCHER = 10 598 FUSIONRIFLE = 11 599 SNIPERRIFLE = 12 600 PULSERIFLE = 13 601 SCOUTRIFLE = 14 602 SIDEARM = 17 603 SWORD = 18 604 MASK = 19 605 SHADER = 20 606 ORNAMENT = 21 607 FUSIONRIFLELINE = 22 608 GRENADELAUNCHER = 23 609 SUBMACHINEGUN = 24 610 TRACERIFLE = 25 611 HELMETARMOR = 26 612 GAUNTLETSARMOR = 27 613 CHESTARMOR = 28 614 LEGARMOR = 29 615 CLASSARMOR = 30 616 BOW = 31 617 DUMMYREPEATABLEBOUNTY = 32
An enum for Destiny 2 inventory items subtype.
620@typing.final 621class ItemTier(int, Enum): 622 """An enum for a Destiny 2 item tier.""" 623 624 NONE = 0 625 BASIC = 3340296461 626 COMMON = 2395677314 627 RARE = 2127292149 628 LEGENDERY = 4008398120 629 EXOTIC = 2759499571
An enum for a Destiny 2 item tier.
555@typing.final 556class ItemType(int, Enum): 557 """Enums for Destiny2's item types.""" 558 559 NONE = 0 560 CURRENCY = 1 561 ARMOR = 2 562 WEAPON = 3 563 MESSAGE = 7 564 ENGRAM = 8 565 CONSUMABLE = 9 566 EXCHANGEMATERIAL = 10 567 MISSIONREWARD = 11 568 QUESTSTEP = 12 569 QUESTSTEPCOMPLETE = 13 570 EMBLEM = 14 571 QUEST = 15 572 SUBCLASS = 16 573 CLANBANNER = 17 574 AURA = 18 575 MOD = 19 576 DUMMY = 20 577 SHIP = 21 578 VEHICLE = 22 579 EMOTE = 23 580 GHOST = 24 581 PACKAGE = 25 582 BOUNTY = 26 583 WRAPPER = 27 584 SEASONALARTIFACT = 28 585 FINISHER = 29
Enums for Destiny2's item types.
45class Iterator(typing.Generic[Item]): 46 """A Flat, In-Memory iterator for sequenced based data. 47 48 Example 49 ------- 50 ```py 51 iterator = Iterator([1, 2, 3]) 52 53 # Map the results. 54 for item in iterator.map(lambda item: item * 2): 55 print(item) 56 # 2 57 # 4 58 59 # Indexing is also supported. 60 print(iterator[0]) 61 # 1 62 63 # Normal iteration. 64 for item in iterator: 65 print(item) 66 # 1 67 # 2 68 # 3 69 70 # Union two iterators. 71 iterator2 = Iterator([4, 5, 6]) 72 final = iterator | iterator2 73 # <Iterator([1, 2, 3, 4, 5, 6])> 74 ``` 75 76 Parameters 77 ---------- 78 items: `collections.Iterable[Item]` 79 The items to iterate over. 80 """ 81 82 __slots__ = ("_items",) 83 84 def __init__(self, items: collections.Iterable[Item]) -> None: 85 self._items = iter(items) 86 87 @typing.overload 88 def collect(self) -> list[Item]: 89 ... 90 91 @typing.overload 92 def collect(self, casting: _B) -> list[_B]: 93 ... 94 95 def collect( 96 self, casting: typing.Optional[_B] = None 97 ) -> typing.Union[list[Item], list[_B]]: 98 """Collects all items in the iterator into a list and cast them into an object if provided. 99 100 Example 101 ------- 102 >>> iterator = Iterator([1, 2, 3]) 103 >>> iterator.collect(casting=str) 104 ["1", "2", "3"] 105 106 Parameters 107 ---------- 108 casting: `T | None` 109 The type to cast the items to. If `None` is provided, the items will be returned as is. 110 111 Raises 112 ------ 113 `StopIteration` 114 If no elements are left in the iterator. 115 """ 116 if casting is not None: 117 return typing.cast(list[_B], list(map(casting, self._items))) 118 119 return list(self._items) 120 121 def next(self) -> Item: 122 """Returns the next item in the iterator. 123 124 Example 125 ------- 126 ```py 127 iterator = Iterator(["1", "2", "3"]) 128 item = iterator.next() 129 assert item == "1" 130 item = iterator.next() 131 assert item == "2" 132 ``` 133 134 Raises 135 ------ 136 `StopIteration` 137 If no elements are left in the iterator. 138 """ 139 try: 140 return self.__next__() 141 except StopIteration: 142 self._ok() 143 144 def map( 145 self, predicate: collections.Callable[[Item], OtherItem] 146 ) -> Iterator[OtherItem]: 147 """Maps each item in the iterator to its predicated value. 148 149 Example 150 ------- 151 ```py 152 iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value)) 153 print(iterator) 154 # <Iterator([1, 2, 3])> 155 ``` 156 157 Parameters 158 ---------- 159 predicate: `collections.Callable[[Item], OtherItem]` 160 The function to map each item in the iterator to its predicated value. 161 162 Returns 163 ------- 164 `Iterator[OtherItem]` 165 The mapped iterator. 166 167 Raises 168 ------ 169 `StopIteration` 170 If no elements are left in the iterator. 171 """ 172 return Iterator(map(predicate, self._items)) 173 174 def take(self, n: int) -> Iterator[Item]: 175 """Take the first number of items until the number of items are yielded or 176 the end of the iterator is reached. 177 178 Example 179 ------- 180 ```py 181 iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT]) 182 print(iterator.take(2)) 183 # <Iterator([GameMode.RAID, GameMode.STRIKE])> 184 ``` 185 186 Parameters 187 ---------- 188 n: `int` 189 The number of items to take. 190 191 Raises 192 ------ 193 `StopIteration` 194 If no elements are left in the iterator. 195 """ 196 return Iterator(itertools.islice(self._items, n)) 197 198 def take_while( 199 self, predicate: collections.Callable[[Item], bool] 200 ) -> Iterator[Item]: 201 """Yields items from the iterator while predicate returns `True`. 202 203 Example 204 ------- 205 ```py 206 iterator = Iterator([STEAM, XBOX, STADIA]) 207 print(iterator.take_while(lambda platform: platform is not XBOX)) 208 # <Iterator([STEAM])> 209 ``` 210 211 Parameters 212 ---------- 213 predicate: `collections.Callable[[Item], bool]` 214 The function to predicate each item in the iterator. 215 216 Raises 217 ------ 218 `StopIteration` 219 If no elements are left in the iterator. 220 """ 221 return Iterator(itertools.takewhile(predicate, self._items)) 222 223 def drop_while( 224 self, predicate: collections.Callable[[Item], bool] 225 ) -> Iterator[Item]: 226 """Yields items from the iterator while predicate returns `False`. 227 228 Example 229 ------- 230 ```py 231 iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")]) 232 print(iterator.drop_while(lambda membership: membership.name is not "Jim")) 233 # <Iterator([DestinyMembership(name="Bob")])> 234 ``` 235 236 Parameters 237 ---------- 238 predicate: `collections.Callable[[Item], bool]` 239 The function to predicate each item in the iterator. 240 241 Raises 242 ------ 243 `StopIteration` 244 If no elements are left in the iterator. 245 """ 246 return Iterator(itertools.dropwhile(predicate, self._items)) 247 248 def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]: 249 """Filters the iterator to only yield items that match the predicate. 250 251 Example 252 ------- 253 ```py 254 names = Iterator(["Jim", "Bob", "Mike", "Jess"]) 255 print(names.filter(lambda n: n != "Jim")) 256 # <Iterator(["Bob", "Mike", "Jess"])> 257 ``` 258 """ 259 return Iterator(filter(predicate, self._items)) 260 261 def skip(self, n: int) -> Iterator[Item]: 262 """Skips the first number of items in the iterator. 263 264 Example 265 ------- 266 ```py 267 iterator = Iterator([STEAM, XBOX, STADIA]) 268 print(iterator.skip(1)) 269 # <Iterator([XBOX, STADIA])> 270 ``` 271 """ 272 return Iterator(itertools.islice(self._items, n, None)) 273 274 def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]: 275 """Zips the iterator with another iterable. 276 277 Example 278 ------- 279 ```py 280 iterator = Iterator([1, 3, 5]) 281 other = Iterator([2, 4, 6]) 282 for item, other_item in iterator.zip(other): 283 print(item, other_item) 284 # <Iterator([(1, 2), (3, 4), (5, 6)])> 285 ``` 286 287 Parameters 288 ---------- 289 other: `Iterator[OtherItem]` 290 The iterable to zip with. 291 292 Raises 293 ------ 294 `StopIteration` 295 If no elements are left in the iterator. 296 """ 297 return Iterator(zip(self._items, other)) 298 299 def all(self, predicate: collections.Callable[[Item], bool]) -> bool: 300 """`True` if all items in the iterator match the predicate. 301 302 Example 303 ------- 304 ```py 305 iterator = Iterator([1, 2, 3]) 306 while iterator.all(lambda item: isinstance(item, int)): 307 print("Still all integers") 308 continue 309 # Still all integers 310 ``` 311 312 Parameters 313 ---------- 314 predicate: `collections.Callable[[Item], bool]` 315 The function to test each item in the iterator. 316 317 Raises 318 ------ 319 `StopIteration` 320 If no elements are left in the iterator. 321 """ 322 return all(predicate(item) for item in self) 323 324 def any(self, predicate: collections.Callable[[Item], bool]) -> bool: 325 """`True` if any items in the iterator match the predicate. 326 327 Example 328 ------- 329 ```py 330 iterator = Iterator([1, 2, 3]) 331 if iterator.any(lambda item: isinstance(item, int)): 332 print("At least one item is an int.") 333 # At least one item is an int. 334 ``` 335 336 Parameters 337 ---------- 338 predicate: `collections.Callable[[Item], bool]` 339 The function to test each item in the iterator. 340 341 Raises 342 ------ 343 `StopIteration` 344 If no elements are left in the iterator. 345 """ 346 return any(predicate(item) for item in self) 347 348 def sort( 349 self, 350 *, 351 key: collections.Callable[[Item], typeshed.SupportsRichComparison], 352 reverse: bool = False, 353 ) -> Iterator[Item]: 354 """Sorts the iterator. 355 356 Example 357 ------- 358 ```py 359 iterator = Iterator([3, 1, 6, 7]) 360 print(iterator.sort(key=lambda item: item)) 361 # <Iterator([1, 3, 6, 7])> 362 ``` 363 364 Parameters 365 ---------- 366 key: `collections.Callable[[Item], Any]` 367 The function to sort by. 368 reverse: `bool` 369 Whether to reverse the sort. 370 371 Raises 372 ------ 373 `StopIteration` 374 If no elements are left in the iterator. 375 """ 376 return Iterator(sorted(self._items, key=key, reverse=reverse)) 377 378 def first(self) -> Item: 379 """Returns the first item in the iterator. 380 381 Example 382 ------- 383 ```py 384 iterator = Iterator([3, 1, 6, 7]) 385 print(iterator.first()) 386 3 387 ``` 388 389 Raises 390 ------ 391 `StopIteration` 392 If no elements are left in the iterator. 393 """ 394 return self.take(1).next() 395 396 def reversed(self) -> Iterator[Item]: 397 """Returns a new iterator that yields the items in the iterator in reverse order. 398 399 Example 400 ------- 401 ```py 402 iterator = Iterator([3, 1, 6, 7]) 403 print(iterator.reversed()) 404 # <Iterator([7, 6, 1, 3])> 405 ``` 406 407 Raises 408 ------ 409 `StopIteration` 410 If no elements are left in the iterator. 411 """ 412 return Iterator(reversed(self.collect())) 413 414 def count(self) -> int: 415 """Returns the number of items in the iterator. 416 417 Example 418 ------- 419 ```py 420 iterator = Iterator([3, 1, 6, 7]) 421 print(iterator.count()) 422 4 423 ``` 424 """ 425 count = 0 426 for _ in self: 427 count += 1 428 429 return count 430 431 def union(self, other: Iterator[Item]) -> Iterator[Item]: 432 """Returns a new iterator that yields all items from both iterators. 433 434 Example 435 ------- 436 ```py 437 iterator = Iterator([1, 2, 3]) 438 other = Iterator([4, 5, 6]) 439 print(iterator.union(other)) 440 # <Iterator([1, 2, 3, 4, 5, 6])> 441 ``` 442 443 Parameters 444 ---------- 445 other: `Iterator[Item]` 446 The iterable to union with. 447 448 Raises 449 ------ 450 `StopIteration` 451 If no elements are left in the iterator. 452 """ 453 return Iterator(itertools.chain(self._items, other)) 454 455 def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None: 456 """Calls the function on each item in the iterator. 457 458 Example 459 ------- 460 ```py 461 iterator = Iterator([1, 2, 3]) 462 iterator.for_each(lambda item: print(item)) 463 # 1 464 # 2 465 # 3 466 ``` 467 468 Parameters 469 ---------- 470 func: `typeshed.Callable[[Item], None]` 471 The function to call on each item in the iterator. 472 """ 473 for item in self: 474 func(item) 475 476 async def async_for_each( 477 self, 478 func: collections.Callable[[Item], collections.Coroutine[None, None, None]], 479 ) -> None: 480 """Calls the async function on each item in the iterator concurrently. 481 482 Example 483 ------- 484 ```py 485 async def signup(username: str) -> None: 486 async with aiohttp.request('POST', '...') as r: 487 # Actual logic. 488 ... 489 490 async def main(): 491 users = aiobungie.into_iter(["user_danny", "user_jojo"]) 492 await users.async_for_each(lambda username: signup(username)) 493 ``` 494 495 Parameters 496 ---------- 497 func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]` 498 The async function to call on each item in the iterator. 499 """ 500 await _helpers.awaits(*(func(item) for item in self)) 501 502 def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]: 503 """Returns a new iterator that yields tuples of the index and item. 504 505 Example 506 ------- 507 ```py 508 iterator = Iterator([1, 2, 3]) 509 for index, item in iterator.enumerate(): 510 print(index, item) 511 # 0 1 512 # 1 2 513 # 2 3 514 ``` 515 516 Raises 517 ------ 518 `StopIteration` 519 If no elements are left in the iterator. 520 """ 521 return Iterator(enumerate(self._items, start=start)) 522 523 def _ok(self) -> typing.NoReturn: 524 raise StopIteration("No more items in the iterator.") from None 525 526 def __getitem__(self, index: int) -> Item: 527 try: 528 return self.skip(index).first() 529 except IndexError: 530 self._ok() 531 532 def __or__(self, other: Iterator[Item]) -> Iterator[Item]: 533 return self.union(other) 534 535 # This is a never. 536 def __setitem__(self) -> typing.NoReturn: 537 raise TypeError( 538 f"{type(self).__name__} doesn't support item assignment." 539 ) from None 540 541 def __repr__(self) -> str: 542 return f'<{self.__class__.__name__}({", ".join([str(item) for item in self])})>' 543 544 def __len__(self) -> int: 545 return self.count() 546 547 def __iter__(self) -> Iterator[Item]: 548 return self 549 550 def __next__(self) -> Item: 551 try: 552 item = next(self._items) 553 except StopIteration: 554 self._ok() 555 556 return item
A Flat, In-Memory iterator for sequenced based data.
Example
iterator = Iterator([1, 2, 3])
# Map the results.
for item in iterator.map(lambda item: item * 2):
print(item)
# 2
# 4
# Indexing is also supported.
print(iterator[0])
# 1
# Normal iteration.
for item in iterator:
print(item)
# 1
# 2
# 3
# Union two iterators.
iterator2 = Iterator([4, 5, 6])
final = iterator | iterator2
# <Iterator([1, 2, 3, 4, 5, 6])>
Parameters
- items (
collections.Iterable[Item]): The items to iterate over.
95 def collect( 96 self, casting: typing.Optional[_B] = None 97 ) -> typing.Union[list[Item], list[_B]]: 98 """Collects all items in the iterator into a list and cast them into an object if provided. 99 100 Example 101 ------- 102 >>> iterator = Iterator([1, 2, 3]) 103 >>> iterator.collect(casting=str) 104 ["1", "2", "3"] 105 106 Parameters 107 ---------- 108 casting: `T | None` 109 The type to cast the items to. If `None` is provided, the items will be returned as is. 110 111 Raises 112 ------ 113 `StopIteration` 114 If no elements are left in the iterator. 115 """ 116 if casting is not None: 117 return typing.cast(list[_B], list(map(casting, self._items))) 118 119 return list(self._items)
Collects all items in the iterator into a list and cast them into an object if provided.
Example
>>> iterator = Iterator([1, 2, 3])
>>> iterator.collect(casting=str)
["1", "2", "3"]
Parameters
- casting (
T | None): The type to cast the items to. IfNoneis provided, the items will be returned as is.
Raises
StopIteration: If no elements are left in the iterator.
121 def next(self) -> Item: 122 """Returns the next item in the iterator. 123 124 Example 125 ------- 126 ```py 127 iterator = Iterator(["1", "2", "3"]) 128 item = iterator.next() 129 assert item == "1" 130 item = iterator.next() 131 assert item == "2" 132 ``` 133 134 Raises 135 ------ 136 `StopIteration` 137 If no elements are left in the iterator. 138 """ 139 try: 140 return self.__next__() 141 except StopIteration: 142 self._ok()
Returns the next item in the iterator.
Example
iterator = Iterator(["1", "2", "3"])
item = iterator.next()
assert item == "1"
item = iterator.next()
assert item == "2"
Raises
StopIteration: If no elements are left in the iterator.
144 def map( 145 self, predicate: collections.Callable[[Item], OtherItem] 146 ) -> Iterator[OtherItem]: 147 """Maps each item in the iterator to its predicated value. 148 149 Example 150 ------- 151 ```py 152 iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value)) 153 print(iterator) 154 # <Iterator([1, 2, 3])> 155 ``` 156 157 Parameters 158 ---------- 159 predicate: `collections.Callable[[Item], OtherItem]` 160 The function to map each item in the iterator to its predicated value. 161 162 Returns 163 ------- 164 `Iterator[OtherItem]` 165 The mapped iterator. 166 167 Raises 168 ------ 169 `StopIteration` 170 If no elements are left in the iterator. 171 """ 172 return Iterator(map(predicate, self._items))
Maps each item in the iterator to its predicated value.
Example
iterator = Iterator(["1", "2", "3"]).map(lambda value: int(value))
print(iterator)
# <Iterator([1, 2, 3])>
Parameters
- predicate (
collections.Callable[[Item], OtherItem]): The function to map each item in the iterator to its predicated value.
Returns
Iterator[OtherItem]: The mapped iterator.
Raises
StopIteration: If no elements are left in the iterator.
174 def take(self, n: int) -> Iterator[Item]: 175 """Take the first number of items until the number of items are yielded or 176 the end of the iterator is reached. 177 178 Example 179 ------- 180 ```py 181 iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT]) 182 print(iterator.take(2)) 183 # <Iterator([GameMode.RAID, GameMode.STRIKE])> 184 ``` 185 186 Parameters 187 ---------- 188 n: `int` 189 The number of items to take. 190 191 Raises 192 ------ 193 `StopIteration` 194 If no elements are left in the iterator. 195 """ 196 return Iterator(itertools.islice(self._items, n))
Take the first number of items until the number of items are yielded or the end of the iterator is reached.
Example
iterator = Iterator([GameMode.RAID, GameMode.STRIKE, GameMode.GAMBIT])
print(iterator.take(2))
# <Iterator([GameMode.RAID, GameMode.STRIKE])>
Parameters
- n (
int): The number of items to take.
Raises
StopIteration: If no elements are left in the iterator.
198 def take_while( 199 self, predicate: collections.Callable[[Item], bool] 200 ) -> Iterator[Item]: 201 """Yields items from the iterator while predicate returns `True`. 202 203 Example 204 ------- 205 ```py 206 iterator = Iterator([STEAM, XBOX, STADIA]) 207 print(iterator.take_while(lambda platform: platform is not XBOX)) 208 # <Iterator([STEAM])> 209 ``` 210 211 Parameters 212 ---------- 213 predicate: `collections.Callable[[Item], bool]` 214 The function to predicate each item in the iterator. 215 216 Raises 217 ------ 218 `StopIteration` 219 If no elements are left in the iterator. 220 """ 221 return Iterator(itertools.takewhile(predicate, self._items))
Yields items from the iterator while predicate returns True.
Example
iterator = Iterator([STEAM, XBOX, STADIA])
print(iterator.take_while(lambda platform: platform is not XBOX))
# <Iterator([STEAM])>
Parameters
- predicate (
collections.Callable[[Item], bool]): The function to predicate each item in the iterator.
Raises
StopIteration: If no elements are left in the iterator.
223 def drop_while( 224 self, predicate: collections.Callable[[Item], bool] 225 ) -> Iterator[Item]: 226 """Yields items from the iterator while predicate returns `False`. 227 228 Example 229 ------- 230 ```py 231 iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")]) 232 print(iterator.drop_while(lambda membership: membership.name is not "Jim")) 233 # <Iterator([DestinyMembership(name="Bob")])> 234 ``` 235 236 Parameters 237 ---------- 238 predicate: `collections.Callable[[Item], bool]` 239 The function to predicate each item in the iterator. 240 241 Raises 242 ------ 243 `StopIteration` 244 If no elements are left in the iterator. 245 """ 246 return Iterator(itertools.dropwhile(predicate, self._items))
Yields items from the iterator while predicate returns False.
Example
iterator = Iterator([DestinyMembership(name="Jim"), DestinyMembership(name="Bob")])
print(iterator.drop_while(lambda membership: membership.name is not "Jim"))
# <Iterator([DestinyMembership(name="Bob")])>
Parameters
- predicate (
collections.Callable[[Item], bool]): The function to predicate each item in the iterator.
Raises
StopIteration: If no elements are left in the iterator.
248 def filter(self, predicate: collections.Callable[[Item], bool]) -> Iterator[Item]: 249 """Filters the iterator to only yield items that match the predicate. 250 251 Example 252 ------- 253 ```py 254 names = Iterator(["Jim", "Bob", "Mike", "Jess"]) 255 print(names.filter(lambda n: n != "Jim")) 256 # <Iterator(["Bob", "Mike", "Jess"])> 257 ``` 258 """ 259 return Iterator(filter(predicate, self._items))
Filters the iterator to only yield items that match the predicate.
Example
names = Iterator(["Jim", "Bob", "Mike", "Jess"])
print(names.filter(lambda n: n != "Jim"))
# <Iterator(["Bob", "Mike", "Jess"])>
261 def skip(self, n: int) -> Iterator[Item]: 262 """Skips the first number of items in the iterator. 263 264 Example 265 ------- 266 ```py 267 iterator = Iterator([STEAM, XBOX, STADIA]) 268 print(iterator.skip(1)) 269 # <Iterator([XBOX, STADIA])> 270 ``` 271 """ 272 return Iterator(itertools.islice(self._items, n, None))
Skips the first number of items in the iterator.
Example
iterator = Iterator([STEAM, XBOX, STADIA])
print(iterator.skip(1))
# <Iterator([XBOX, STADIA])>
274 def zip(self, other: Iterator[OtherItem]) -> Iterator[tuple[Item, OtherItem]]: 275 """Zips the iterator with another iterable. 276 277 Example 278 ------- 279 ```py 280 iterator = Iterator([1, 3, 5]) 281 other = Iterator([2, 4, 6]) 282 for item, other_item in iterator.zip(other): 283 print(item, other_item) 284 # <Iterator([(1, 2), (3, 4), (5, 6)])> 285 ``` 286 287 Parameters 288 ---------- 289 other: `Iterator[OtherItem]` 290 The iterable to zip with. 291 292 Raises 293 ------ 294 `StopIteration` 295 If no elements are left in the iterator. 296 """ 297 return Iterator(zip(self._items, other))
Zips the iterator with another iterable.
Example
iterator = Iterator([1, 3, 5])
other = Iterator([2, 4, 6])
for item, other_item in iterator.zip(other):
print(item, other_item)
# <Iterator([(1, 2), (3, 4), (5, 6)])>
Parameters
- other (
Iterator[OtherItem]): The iterable to zip with.
Raises
StopIteration: If no elements are left in the iterator.
299 def all(self, predicate: collections.Callable[[Item], bool]) -> bool: 300 """`True` if all items in the iterator match the predicate. 301 302 Example 303 ------- 304 ```py 305 iterator = Iterator([1, 2, 3]) 306 while iterator.all(lambda item: isinstance(item, int)): 307 print("Still all integers") 308 continue 309 # Still all integers 310 ``` 311 312 Parameters 313 ---------- 314 predicate: `collections.Callable[[Item], bool]` 315 The function to test each item in the iterator. 316 317 Raises 318 ------ 319 `StopIteration` 320 If no elements are left in the iterator. 321 """ 322 return all(predicate(item) for item in self)
True if all items in the iterator match the predicate.
Example
iterator = Iterator([1, 2, 3])
while iterator.all(lambda item: isinstance(item, int)):
print("Still all integers")
continue
# Still all integers
Parameters
- predicate (
collections.Callable[[Item], bool]): The function to test each item in the iterator.
Raises
StopIteration: If no elements are left in the iterator.
324 def any(self, predicate: collections.Callable[[Item], bool]) -> bool: 325 """`True` if any items in the iterator match the predicate. 326 327 Example 328 ------- 329 ```py 330 iterator = Iterator([1, 2, 3]) 331 if iterator.any(lambda item: isinstance(item, int)): 332 print("At least one item is an int.") 333 # At least one item is an int. 334 ``` 335 336 Parameters 337 ---------- 338 predicate: `collections.Callable[[Item], bool]` 339 The function to test each item in the iterator. 340 341 Raises 342 ------ 343 `StopIteration` 344 If no elements are left in the iterator. 345 """ 346 return any(predicate(item) for item in self)
True if any items in the iterator match the predicate.
Example
iterator = Iterator([1, 2, 3])
if iterator.any(lambda item: isinstance(item, int)):
print("At least one item is an int.")
# At least one item is an int.
Parameters
- predicate (
collections.Callable[[Item], bool]): The function to test each item in the iterator.
Raises
StopIteration: If no elements are left in the iterator.
348 def sort( 349 self, 350 *, 351 key: collections.Callable[[Item], typeshed.SupportsRichComparison], 352 reverse: bool = False, 353 ) -> Iterator[Item]: 354 """Sorts the iterator. 355 356 Example 357 ------- 358 ```py 359 iterator = Iterator([3, 1, 6, 7]) 360 print(iterator.sort(key=lambda item: item)) 361 # <Iterator([1, 3, 6, 7])> 362 ``` 363 364 Parameters 365 ---------- 366 key: `collections.Callable[[Item], Any]` 367 The function to sort by. 368 reverse: `bool` 369 Whether to reverse the sort. 370 371 Raises 372 ------ 373 `StopIteration` 374 If no elements are left in the iterator. 375 """ 376 return Iterator(sorted(self._items, key=key, reverse=reverse))
Sorts the iterator.
Example
iterator = Iterator([3, 1, 6, 7])
print(iterator.sort(key=lambda item: item))
# <Iterator([1, 3, 6, 7])>
Parameters
- key (
collections.Callable[[Item], Any]): The function to sort by. - reverse (
bool): Whether to reverse the sort.
Raises
StopIteration: If no elements are left in the iterator.
378 def first(self) -> Item: 379 """Returns the first item in the iterator. 380 381 Example 382 ------- 383 ```py 384 iterator = Iterator([3, 1, 6, 7]) 385 print(iterator.first()) 386 3 387 ``` 388 389 Raises 390 ------ 391 `StopIteration` 392 If no elements are left in the iterator. 393 """ 394 return self.take(1).next()
Returns the first item in the iterator.
Example
iterator = Iterator([3, 1, 6, 7])
print(iterator.first())
3
Raises
StopIteration: If no elements are left in the iterator.
396 def reversed(self) -> Iterator[Item]: 397 """Returns a new iterator that yields the items in the iterator in reverse order. 398 399 Example 400 ------- 401 ```py 402 iterator = Iterator([3, 1, 6, 7]) 403 print(iterator.reversed()) 404 # <Iterator([7, 6, 1, 3])> 405 ``` 406 407 Raises 408 ------ 409 `StopIteration` 410 If no elements are left in the iterator. 411 """ 412 return Iterator(reversed(self.collect()))
Returns a new iterator that yields the items in the iterator in reverse order.
Example
iterator = Iterator([3, 1, 6, 7])
print(iterator.reversed())
# <Iterator([7, 6, 1, 3])>
Raises
StopIteration: If no elements are left in the iterator.
414 def count(self) -> int: 415 """Returns the number of items in the iterator. 416 417 Example 418 ------- 419 ```py 420 iterator = Iterator([3, 1, 6, 7]) 421 print(iterator.count()) 422 4 423 ``` 424 """ 425 count = 0 426 for _ in self: 427 count += 1 428 429 return count
Returns the number of items in the iterator.
Example
iterator = Iterator([3, 1, 6, 7])
print(iterator.count())
4
431 def union(self, other: Iterator[Item]) -> Iterator[Item]: 432 """Returns a new iterator that yields all items from both iterators. 433 434 Example 435 ------- 436 ```py 437 iterator = Iterator([1, 2, 3]) 438 other = Iterator([4, 5, 6]) 439 print(iterator.union(other)) 440 # <Iterator([1, 2, 3, 4, 5, 6])> 441 ``` 442 443 Parameters 444 ---------- 445 other: `Iterator[Item]` 446 The iterable to union with. 447 448 Raises 449 ------ 450 `StopIteration` 451 If no elements are left in the iterator. 452 """ 453 return Iterator(itertools.chain(self._items, other))
Returns a new iterator that yields all items from both iterators.
Example
iterator = Iterator([1, 2, 3])
other = Iterator([4, 5, 6])
print(iterator.union(other))
# <Iterator([1, 2, 3, 4, 5, 6])>
Parameters
- other (
Iterator[Item]): The iterable to union with.
Raises
StopIteration: If no elements are left in the iterator.
455 def for_each(self, func: collections.Callable[[Item], typing.Any]) -> None: 456 """Calls the function on each item in the iterator. 457 458 Example 459 ------- 460 ```py 461 iterator = Iterator([1, 2, 3]) 462 iterator.for_each(lambda item: print(item)) 463 # 1 464 # 2 465 # 3 466 ``` 467 468 Parameters 469 ---------- 470 func: `typeshed.Callable[[Item], None]` 471 The function to call on each item in the iterator. 472 """ 473 for item in self: 474 func(item)
Calls the function on each item in the iterator.
Example
iterator = Iterator([1, 2, 3])
iterator.for_each(lambda item: print(item))
# 1
# 2
# 3
Parameters
- func (
typeshed.Callable[[Item], None]): The function to call on each item in the iterator.
476 async def async_for_each( 477 self, 478 func: collections.Callable[[Item], collections.Coroutine[None, None, None]], 479 ) -> None: 480 """Calls the async function on each item in the iterator concurrently. 481 482 Example 483 ------- 484 ```py 485 async def signup(username: str) -> None: 486 async with aiohttp.request('POST', '...') as r: 487 # Actual logic. 488 ... 489 490 async def main(): 491 users = aiobungie.into_iter(["user_danny", "user_jojo"]) 492 await users.async_for_each(lambda username: signup(username)) 493 ``` 494 495 Parameters 496 ---------- 497 func: `collections.Callable[[Item], collections.Coroutine[None, None, None]]` 498 The async function to call on each item in the iterator. 499 """ 500 await _helpers.awaits(*(func(item) for item in self))
Calls the async function on each item in the iterator concurrently.
Example
async def signup(username: str) -> None:
async with aiohttp.request('POST', '...') as r:
# Actual logic.
...
async def main():
users = aiobungie.into_iter(["user_danny", "user_jojo"])
await users.async_for_each(lambda username: signup(username))
Parameters
- func (
collections.Callable[[Item], collections.Coroutine[None, None, None]]): The async function to call on each item in the iterator.
502 def enumerate(self, *, start: int = 0) -> Iterator[tuple[int, Item]]: 503 """Returns a new iterator that yields tuples of the index and item. 504 505 Example 506 ------- 507 ```py 508 iterator = Iterator([1, 2, 3]) 509 for index, item in iterator.enumerate(): 510 print(index, item) 511 # 0 1 512 # 1 2 513 # 2 3 514 ``` 515 516 Raises 517 ------ 518 `StopIteration` 519 If no elements are left in the iterator. 520 """ 521 return Iterator(enumerate(self._items, start=start))
Returns a new iterator that yields tuples of the index and item.
Example
iterator = Iterator([1, 2, 3])
for index, item in iterator.enumerate():
print(index, item)
# 0 1
# 1 2
# 2 3
Raises
StopIteration: If no elements are left in the iterator.
712@typing.final 713class MembershipOption(int, Enum): 714 """A enum for GroupV2 membership options.""" 715 716 REVIEWD = 0 717 OPEN = 1 718 CLOSED = 2
A enum for GroupV2 membership options.
460@typing.final 461class MembershipType(int, Enum): 462 """An Enum for Bungie membership types.""" 463 464 NONE = 0 465 XBOX = 1 466 PSN = 2 467 STEAM = 3 468 BLIZZARD = 4 469 STADIA = 5 470 EPIC_GAMES_STORE = 6 471 DEMON = 10 472 BUNGIE = 254 473 ALL = -1
An Enum for Bungie membership types.
182@attrs.define(auto_exc=True) 183class MembershipTypeError(BadRequest): 184 """A bad request error raised when passing wrong membership to the request. 185 186 Those fields are useful since it returns the correct membership and id which can be used 187 to make the request again with those fields. 188 189 Example 190 ------- 191 ```py 192 try: 193 profile = await client.fetch_profile( 194 member_id=1, 195 type=aiobungie.MembershipType.STADIA, 196 components=[] 197 ) 198 199 # Membership type is wrong! 200 except aiobungie.MembershipTypeError as err: 201 correct_membersip = err.into_membership() 202 profile_id = err.membership_id 203 204 # Recall the method. 205 profile = await client.fetch_profile( 206 member_id=profile_id, 207 type=correct_membership, 208 components=[] 209 ) 210 ``` 211 """ 212 213 membership_type: str 214 """The errored membership type passed to the request.""" 215 216 membership_id: int 217 """The errored user's membership id.""" 218 219 required_membership: str 220 """The required correct membership for errored user.""" 221 222 def into_membership( 223 self, value: typing.Optional[str] = None 224 ) -> enums.MembershipType: 225 """Turn the required membership from `str` into `aiobungie.Membership` type. 226 227 If value parameter is not provided it will fall back to the required membership. 228 """ 229 if value is None: 230 return _DETERMINE_MSHIP(self.required_membership) 231 return _DETERMINE_MSHIP(value) 232 233 def __str__(self) -> str: 234 return ( 235 f"Expected membership: {self.into_membership().name.replace('_', '').title()}, " 236 f"But got {self.into_membership(self.membership_type)} for id {self.membership_id}" 237 ) 238 239 def __int__(self) -> int: 240 return int(self.membership_id)
A bad request error raised when passing wrong membership to the request.
Those fields are useful since it returns the correct membership and id which can be used to make the request again with those fields.
Example
try:
profile = await client.fetch_profile(
member_id=1,
type=aiobungie.MembershipType.STADIA,
components=[]
)
# Membership type is wrong!
except aiobungie.MembershipTypeError as err:
correct_membersip = err.into_membership()
profile_id = err.membership_id
# Recall the method.
profile = await client.fetch_profile(
member_id=profile_id,
type=correct_membership,
components=[]
)
2def __init__(self, message, url, body, headers, membership_type, membership_id, required_membership): 3 self.message = message 4 self.url = url 5 self.body = body 6 self.headers = headers 7 self.http_status = attr_dict['http_status'].default 8 self.membership_type = membership_type 9 self.membership_id = membership_id 10 self.required_membership = required_membership 11 BaseException.__init__(self, self.message,self.url,self.body,self.headers,self.membership_type,self.membership_id,self.required_membership)
Method generated by attrs for class MembershipTypeError.
222 def into_membership( 223 self, value: typing.Optional[str] = None 224 ) -> enums.MembershipType: 225 """Turn the required membership from `str` into `aiobungie.Membership` type. 226 227 If value parameter is not provided it will fall back to the required membership. 228 """ 229 if value is None: 230 return _DETERMINE_MSHIP(self.required_membership) 231 return _DETERMINE_MSHIP(value)
Turn the required membership from str into aiobungie.Membership type.
If value parameter is not provided it will fall back to the required membership.
Inherited Members
- builtins.BaseException
- with_traceback
- args
505@typing.final 506class MilestoneType(int, Enum): 507 """An Enum for Destiny 2 milestone types.""" 508 509 UNKNOWN = 0 510 TUTORIAL = 1 511 ONETIME = 2 512 WEEKLY = 3 513 DAILY = 4 514 SPECIAL = 5
An Enum for Destiny 2 milestone types.
146@attrs.define(auto_exc=True) 147class NotFound(HTTPException): 148 """Raised when an unknown resource was not found.""" 149 150 http_status: http.HTTPStatus = attrs.field( 151 default=http.HTTPStatus.NOT_FOUND, init=False 152 )
Raised when an unknown resource was not found.
2def __init__(self, *, error_code, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.throttle_seconds = throttle_seconds 5 self.url = url 6 self.body = body 7 self.headers = headers 8 self.message = message 9 self.error_status = error_status 10 self.message_data = message_data 11 self.http_status = attr_dict['http_status'].default 12 BaseException.__init__(self, self.error_code,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class NotFound.
Inherited Members
- builtins.BaseException
- with_traceback
- args
94@typing.final 95class ObjectiveUIStyle(int, enums.Enum): 96 NONE = 0 97 HIGHLIGHTED = 1 98 CRAFTING_WEAPON_LEVEL = 2 99 CRAFTING_WEAPON_LEVEL_PROGRESS = 3 100 CRAFTING_WEAPON_TIMESTAMP = 4 101 CRAFTING_MEMENTOS = 5 102 CRAFTING_MEMENTO_TITLE = 6
An enumeration.
230@typing.final 231class Place(int, Enum): 232 """An Enum for Destiny 2 Places and NOT Planets""" 233 234 ORBIT = 2961497387 235 SOCIAL = 4151112093 236 LIGHT_HOUSE = 4276116472 237 EXPLORE = 3497767639
An Enum for Destiny 2 Places and NOT Planets
195@typing.final 196class Planet(int, Enum): 197 """An Enum for all available planets in Destiny 2.""" 198 199 UNKNOWN = 0 200 """Unknown space""" 201 202 EARTH = 3747705955 203 """Earth""" 204 205 DREAMING_CITY = 2877881518 206 """The Dreaming city.""" 207 208 NESSUS = 3526908984 209 """Nessus""" 210 211 MOON = 3325508439 212 """The Moon""" 213 214 COSMODROME = 3990611421 215 """The Cosmodrome""" 216 217 TANGLED_SHORE = 3821439926 218 """The Tangled Shore""" 219 220 VENUS = 3871070152 221 """Venus""" 222 223 EAZ = 541863059 # Exclusive event. 224 """European Aerial Zone""" 225 226 EUROPA = 1729879943 227 """Europa"""
An Enum for all available planets in Destiny 2.
682@typing.final 683class Presence(int, Enum): 684 """An enum for a bungie friend status.""" 685 686 OFFLINE_OR_UNKNOWN = 0 687 ONLINE = 1
An enum for a bungie friend status.
770@typing.final 771class PrivacySetting(int, Enum): 772 """An enum for players's privacy settings.""" 773 774 OPEN = 0 775 CLAN_AND_FRIENDS = 1 776 FRIENDS_ONLY = 2 777 INVITE_ONLY = 3 778 CLOSED = 4
An enum for players's privacy settings.
313class RESTClient(interfaces.RESTInterface): 314 """A RESTful client implementation for Bungie's API. 315 316 This client is designed to only make HTTP requests and return JSON objects 317 to provide RESTful functionality. 318 319 This client is also used within `aiobungie.Client` which deserialize those returned JSON objects 320 using the factory into Pythonic data classes objects which provide Python functionality. 321 322 Example 323 ------- 324 ```py 325 import aiobungie 326 327 async def main(): 328 async with aiobungie.RESTClient("TOKEN") as rest_client: 329 req = await rest_client.fetch_clan_members(4389205) 330 clan_members = req['results'] 331 for member in clan_members: 332 for k, v in member['destinyUserInfo'].items(): 333 print(k, v) 334 ``` 335 336 Parameters 337 ---------- 338 token : `str` 339 A valid application token from Bungie's developer portal. 340 341 Other Parameters 342 ---------------- 343 max_retries : `int` 344 The max retries number to retry if the request hit a `5xx` status code. 345 client_secret : `typing.Optional[str]` 346 An optional application client secret, 347 This is only needed if you're fetching OAuth2 tokens with this client. 348 client_id : `typing.Optional[int]` 349 An optional application client id, 350 This is only needed if you're fetching OAuth2 tokens with this client. 351 enable_debugging : `bool | str` 352 Whether to enable logging responses or not. 353 354 Logging Levels 355 -------------- 356 * `False`: This will disable logging. 357 * `True`: This will set the level to `DEBUG` and enable logging minimal information. 358 * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information. 359 """ 360 361 __slots__ = ( 362 "_token", 363 "_session", 364 "_lock", 365 "_max_retries", 366 "_client_secret", 367 "_client_id", 368 "_metadata", 369 ) 370 371 def __init__( 372 self, 373 token: str, 374 /, 375 *, 376 client_secret: typing.Optional[str] = None, 377 client_id: typing.Optional[int] = None, 378 client_session: typing.Optional[aiohttp.ClientSession] = None, 379 max_retries: int = 4, 380 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, 381 ) -> None: 382 self._session: typing.Optional[aiohttp.ClientSession] = client_session 383 self._lock: typing.Optional[asyncio.Lock] = None 384 self._client_secret = client_secret 385 self._client_id = client_id 386 self._token: str = token 387 self._max_retries = max_retries 388 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} 389 390 self._set_debug_level(enable_debugging) 391 392 @property 393 def client_id(self) -> typing.Optional[int]: 394 return self._client_id 395 396 @property 397 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: 398 return self._metadata 399 400 @property 401 def is_alive(self) -> bool: 402 return self._session is not None 403 404 @typing.final 405 async def close(self) -> None: 406 if self._session is None: 407 raise RuntimeError("REST client is not running.") 408 409 await self._session.close() 410 self._session = None 411 412 @typing.final 413 def open(self) -> None: 414 """Open a new client session. This is called internally with contextmanager usage.""" 415 if self._session: 416 raise RuntimeError("Cannot open REST client when it's already open.") 417 418 self._session = aiohttp.ClientSession( 419 connector=aiohttp.TCPConnector(ssl=False), 420 raise_for_status=False, 421 timeout=aiohttp.ClientTimeout(total=30.0), 422 ) 423 424 @typing.final 425 def enable_debugging( 426 self, 427 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, 428 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, 429 /, 430 ) -> None: 431 self._set_debug_level(level, file) 432 433 @typing.final 434 async def static_request( 435 self, 436 method: typing.Union[RequestMethod, str], 437 path: str, 438 *, 439 auth: typing.Optional[str] = None, 440 json: typing.Optional[dict[str, typing.Any]] = None, 441 ) -> ResponseSig: 442 return await self._request(method, path, auth=auth, json=json) 443 444 @typing.final 445 def build_oauth2_url( 446 self, client_id: typing.Optional[int] = None 447 ) -> typing.Optional[builders.OAuthURL]: 448 client_id = client_id or self._client_id 449 if client_id is None: 450 return None 451 452 return builders.OAuthURL(client_id=client_id) 453 454 @staticmethod 455 def _set_debug_level( 456 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, 457 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, 458 ) -> None: 459 file_handler = logging.FileHandler(file, mode="w") if file else None 460 if level == "TRACE" or level == TRACE: 461 logging.basicConfig( 462 level=TRACE, handlers=[file_handler] if file_handler else None 463 ) 464 465 elif level: 466 logging.basicConfig( 467 level=logging.DEBUG, handlers=[file_handler] if file_handler else None 468 ) 469 470 async def _request( 471 self, 472 method: typing.Union[RequestMethod, str], 473 route: str, 474 *, 475 base: bool = False, 476 oauth2: bool = False, 477 auth: typing.Optional[str] = None, 478 unwrapping: typing.Literal["json", "read"] = "json", 479 json: typing.Optional[dict[str, typing.Any]] = None, 480 headers: typing.Optional[dict[str, typing.Any]] = None, 481 data: typing.Optional[typing.Union[str, dict[str, typing.Any]]] = None, 482 ) -> ResponseSig: 483 # This is not None when opening the client. 484 assert self._session is not None 485 486 retries: int = 0 487 headers = headers or {} 488 489 headers.setdefault(_USER_AGENT_HEADERS, _USER_AGENT) 490 headers["X-API-KEY"] = self._token 491 492 if auth is not None: 493 headers[_AUTH_HEADER] = f"Bearer {auth}" 494 495 # Handling endpoints 496 endpoint = url.BASE 497 498 if not base: 499 endpoint = endpoint + url.REST_EP 500 501 if oauth2: 502 headers["Content-Type"] = "application/x-www-form-urlencoded" 503 endpoint = endpoint + url.TOKEN_EP 504 505 if self._lock is None: 506 self._lock = asyncio.Lock() 507 508 while True: 509 async with (stack := contextlib.AsyncExitStack()): 510 await stack.enter_async_context(self._lock) 511 512 # We make the request here. 513 taken_time = time.monotonic() 514 response = await stack.enter_async_context( 515 self._session.request( 516 method=method, 517 url=f"{endpoint}/{route}", 518 json=json, 519 headers=headers, 520 data=data, 521 ) 522 ) 523 response_time = (time.monotonic() - taken_time) * 1_000 524 525 _LOG.debug( 526 "%s %s %s Time %.4fms", 527 method, 528 f"{endpoint}/{route}", 529 f"{response.status} {response.reason}", 530 response_time, 531 ) 532 533 await self._handle_ratelimit(response, method, route) 534 535 if response.status == http.HTTPStatus.NO_CONTENT: 536 return None 537 538 if 300 > response.status >= 200: 539 if unwrapping == "read": 540 # We need to read the bytes for the manifest response. 541 return await response.read() 542 543 if response.content_type == _APP_JSON: 544 json_data = await response.json() 545 546 _LOG.debug( 547 "%s %s %s Time %.4fms", 548 method, 549 f"{endpoint}/{route}", 550 f"{response.status} {response.reason}", 551 response_time, 552 ) 553 554 if _LOG.isEnabledFor(TRACE): 555 cloned = headers.copy() 556 cloned.update(response.headers) # type: ignore 557 558 _LOG.log( 559 TRACE, 560 "%s", 561 error.stringify_http_message(cloned), 562 ) 563 564 # Return the response. 565 # oauth2 responses are not packed inside a Response object. 566 if oauth2: 567 return json_data # type: ignore[no-any-return] 568 569 return json_data["Response"] # type: ignore[no-any-return] 570 571 if ( 572 response.status in _RETRY_5XX 573 and retries < self._max_retries # noqa: W503 574 ): 575 backoff_ = backoff.ExponentialBackOff(maximum=6) 576 sleep_time = next(backoff_) 577 _LOG.warning( 578 "Got %i - %s. Sleeping for %.2f seconds. Remaining retries: %i", 579 response.status, 580 response.reason, 581 sleep_time, 582 self._max_retries - retries, 583 ) 584 585 retries += 1 586 await asyncio.sleep(sleep_time) 587 continue 588 589 raise await error.raise_error(response) 590 591 if not typing.TYPE_CHECKING: 592 593 def __enter__(self) -> typing.NoReturn: 594 cls = type(self) 595 raise TypeError( 596 f"{cls.__qualname__} is async only, use 'async with' instead." 597 ) 598 599 def __exit__( 600 self, 601 exception_type: typing.Optional[type[BaseException]], 602 exception: typing.Optional[BaseException], 603 exception_traceback: typing.Optional[types.TracebackType], 604 ) -> None: 605 ... 606 607 async def __aenter__(self) -> RESTClient: 608 self.open() 609 return self 610 611 async def __aexit__( 612 self, 613 exception_type: typing.Optional[type[BaseException]], 614 exception: typing.Optional[BaseException], 615 exception_traceback: typing.Optional[types.TracebackType], 616 ) -> None: 617 await self.close() 618 619 # We don't want this to be super complicated. 620 @typing.final 621 async def _handle_ratelimit( 622 self, 623 response: aiohttp.ClientResponse, 624 method: str, 625 route: str, 626 ) -> None: 627 if response.status != http.HTTPStatus.TOO_MANY_REQUESTS: 628 return 629 630 if response.content_type != _APP_JSON: 631 raise error.HTTPError( 632 f"Being ratelimited on non JSON request, {response.content_type}.", 633 http.HTTPStatus.TOO_MANY_REQUESTS, 634 ) 635 636 json: typedefs.JSONObject = await response.json() 637 retry_after = float(json.get("ThrottleSeconds", 15.0)) + 0.1 638 max_calls: int = 0 639 640 while True: 641 if max_calls == 10: 642 # Max retries by default. We raise an error here. 643 raise error.RateLimitedError( 644 body=json, 645 url=str(response.real_url), 646 retry_after=retry_after, 647 ) 648 649 # We sleep for a little bit to avoid funky behavior. 650 _LOG.warning( 651 "We're being ratelimited, Method %s Route %s. Sleeping for %.2fs.", 652 method, 653 route, 654 retry_after, 655 ) 656 await asyncio.sleep(retry_after) 657 max_calls += 1 658 continue 659 660 async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response: 661 if not isinstance(self._client_secret, (str, int)): 662 raise TypeError( 663 "Expected (str, int) for client secret " 664 f"but got {type(self._client_secret).__name__}" # type: ignore 665 ) 666 667 headers = { 668 "client_secret": self._client_secret, 669 } 670 671 data = ( 672 f"grant_type=authorization_code&code={code}" 673 f"&client_id={self._client_id}&client_secret={self._client_secret}" 674 ) 675 676 response = await self._request( 677 RequestMethod.POST, "", headers=headers, data=data, oauth2=True 678 ) 679 assert isinstance(response, dict) 680 return builders.OAuth2Response.build_response(response) 681 682 async def refresh_access_token( 683 self, refresh_token: str, / 684 ) -> builders.OAuth2Response: 685 if not isinstance(self._client_secret, (int, str)): 686 raise TypeError( 687 f"Expected (str, int) for client secret but got {type(self._client_secret).__name__}" # type: ignore 688 ) 689 690 data = { 691 "grant_type": "refresh_token", 692 "refresh_token": refresh_token, 693 "client_id": self._client_id, 694 "client_secret": self._client_secret, 695 "Content-Type": "application/x-www-form-urlencoded", 696 } 697 698 response = await self._request(RequestMethod.POST, "", data=data, oauth2=True) 699 assert isinstance(response, dict) 700 return builders.OAuth2Response.build_response(response) 701 702 async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject: 703 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 704 resp = await self._request( 705 RequestMethod.GET, f"User/GetBungieNetUserById/{id}/" 706 ) 707 assert isinstance(resp, dict) 708 return resp 709 710 async def fetch_user_themes(self) -> typedefs.JSONArray: 711 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 712 resp = await self._request(RequestMethod.GET, "User/GetAvailableThemes/") 713 assert isinstance(resp, list) 714 return resp 715 716 async def fetch_membership_from_id( 717 self, 718 id: int, 719 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 720 /, 721 ) -> typedefs.JSONObject: 722 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 723 resp = await self._request( 724 RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}" 725 ) 726 assert isinstance(resp, dict) 727 return resp 728 729 async def fetch_player( 730 self, 731 name: str, 732 code: int, 733 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, 734 /, 735 ) -> typedefs.JSONArray: 736 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 737 resp = await self._request( 738 RequestMethod.POST, 739 f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}", 740 json={"displayName": name, "displayNameCode": code}, 741 ) 742 assert isinstance(resp, list) 743 return resp 744 745 async def search_users(self, name: str, /) -> typedefs.JSONObject: 746 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 747 resp = await self._request( 748 RequestMethod.POST, 749 "User/Search/GlobalName/0", 750 json={"displayNamePrefix": name}, 751 ) 752 assert isinstance(resp, dict) 753 return resp 754 755 async def fetch_clan_from_id( 756 self, id: int, /, access_token: typing.Optional[str] = None 757 ) -> typedefs.JSONObject: 758 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 759 resp = await self._request( 760 RequestMethod.GET, f"GroupV2/{id}", auth=access_token 761 ) 762 assert isinstance(resp, dict) 763 return resp 764 765 async def fetch_clan( 766 self, 767 name: str, 768 /, 769 access_token: typing.Optional[str] = None, 770 *, 771 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 772 ) -> typedefs.JSONObject: 773 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 774 resp = await self._request( 775 RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token 776 ) 777 assert isinstance(resp, dict) 778 return resp 779 780 async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject: 781 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 782 resp = await self._request( 783 RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/" 784 ) 785 assert isinstance(resp, dict) 786 return resp 787 788 async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray: 789 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 790 resp = await self._request( 791 RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/" 792 ) 793 assert isinstance(resp, list) 794 return resp 795 796 async def fetch_application(self, appid: int, /) -> typedefs.JSONObject: 797 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 798 resp = await self._request(RequestMethod.GET, f"App/Application/{appid}") 799 assert isinstance(resp, dict) 800 return resp 801 802 async def fetch_character( 803 self, 804 member_id: int, 805 membership_type: typedefs.IntAnd[enums.MembershipType], 806 character_id: int, 807 components: list[enums.ComponentType], 808 auth: typing.Optional[str] = None, 809 ) -> typedefs.JSONObject: 810 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 811 collector = _collect_components(components) 812 response = await self._request( 813 RequestMethod.GET, 814 f"Destiny2/{int(membership_type)}/Profile/{member_id}/" 815 f"Character/{character_id}/?components={collector}", 816 auth=auth, 817 ) 818 assert isinstance(response, dict) 819 return response 820 821 async def fetch_activities( 822 self, 823 member_id: int, 824 character_id: int, 825 mode: typedefs.IntAnd[enums.GameMode], 826 membership_type: typedefs.IntAnd[ 827 enums.MembershipType 828 ] = enums.MembershipType.ALL, 829 *, 830 page: int = 0, 831 limit: int = 1, 832 ) -> typedefs.JSONObject: 833 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 834 resp = await self._request( 835 RequestMethod.GET, 836 f"Destiny2/{int(membership_type)}/Account/" 837 f"{member_id}/Character/{character_id}/Stats/Activities" 838 f"/?mode={int(mode)}&count={limit}&page={page}", 839 ) 840 assert isinstance(resp, dict) 841 return resp 842 843 async def fetch_vendor_sales(self) -> typedefs.JSONObject: 844 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 845 resp = await self._request( 846 RequestMethod.GET, 847 f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}", 848 ) 849 assert isinstance(resp, dict) 850 return resp 851 852 async def fetch_profile( 853 self, 854 membership_id: int, 855 type: typedefs.IntAnd[enums.MembershipType], 856 components: list[enums.ComponentType], 857 auth: typing.Optional[str] = None, 858 ) -> typedefs.JSONObject: 859 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 860 collector = _collect_components(components) 861 response = await self._request( 862 RequestMethod.GET, 863 f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}", 864 auth=auth, 865 ) 866 assert isinstance(response, dict) 867 return response 868 869 async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject: 870 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 871 response = await self._request( 872 RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}" 873 ) 874 assert isinstance(response, dict) 875 return response 876 877 async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject: 878 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 879 resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash) 880 assert isinstance(resp, dict) 881 return resp 882 883 async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject: 884 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 885 resp = await self.fetch_entity("DestinyObjectiveDefinition", hash) 886 assert isinstance(resp, dict) 887 return resp 888 889 async def fetch_groups_for_member( 890 self, 891 member_id: int, 892 member_type: typedefs.IntAnd[enums.MembershipType], 893 /, 894 *, 895 filter: int = 0, 896 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 897 ) -> typedefs.JSONObject: 898 resp = await self._request( 899 RequestMethod.GET, 900 f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", 901 ) 902 assert isinstance(resp, dict) 903 return resp 904 905 async def fetch_potential_groups_for_member( 906 self, 907 member_id: int, 908 member_type: typedefs.IntAnd[enums.MembershipType], 909 /, 910 *, 911 filter: int = 0, 912 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 913 ) -> typedefs.JSONObject: 914 resp = await self._request( 915 RequestMethod.GET, 916 f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", 917 ) 918 assert isinstance(resp, dict) 919 return resp 920 921 async def fetch_clan_members( 922 self, 923 clan_id: int, 924 /, 925 *, 926 name: typing.Optional[str] = None, 927 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 928 ) -> typedefs.JSONObject: 929 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 930 resp = await self._request( 931 RequestMethod.GET, 932 f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}¤tpage=1", 933 ) 934 assert isinstance(resp, dict) 935 return resp 936 937 async def fetch_hardlinked_credentials( 938 self, 939 credential: int, 940 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, 941 /, 942 ) -> typedefs.JSONObject: 943 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 944 resp = await self._request( 945 RequestMethod.GET, 946 f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/", 947 ) 948 assert isinstance(resp, dict) 949 return resp 950 951 async def fetch_user_credentials( 952 self, access_token: str, membership_id: int, / 953 ) -> typedefs.JSONArray: 954 resp = await self._request( 955 RequestMethod.GET, 956 f"User/GetCredentialTypesForTargetAccount/{membership_id}", 957 auth=access_token, 958 ) 959 assert isinstance(resp, list) 960 return resp 961 962 async def insert_socket_plug( 963 self, 964 action_token: str, 965 /, 966 instance_id: int, 967 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], 968 character_id: int, 969 membership_type: typedefs.IntAnd[enums.MembershipType], 970 ) -> typedefs.JSONObject: 971 if isinstance(plug, builders.PlugSocketBuilder): 972 plug = plug.collect() 973 974 body = { 975 "actionToken": action_token, 976 "itemInstanceId": instance_id, 977 "plug": plug, 978 "characterId": character_id, 979 "membershipType": int(membership_type), 980 } 981 resp = await self._request( 982 RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body 983 ) 984 assert isinstance(resp, dict) 985 return resp 986 987 async def insert_socket_plug_free( 988 self, 989 access_token: str, 990 /, 991 instance_id: int, 992 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], 993 character_id: int, 994 membership_type: typedefs.IntAnd[enums.MembershipType], 995 ) -> typedefs.JSONObject: 996 if isinstance(plug, builders.PlugSocketBuilder): 997 plug = plug.collect() 998 999 body = { 1000 "itemInstanceId": instance_id, 1001 "plug": plug, 1002 "characterId": character_id, 1003 "membershipType": int(membership_type), 1004 } 1005 resp = await self._request( 1006 RequestMethod.POST, 1007 "Destiny2/Actions/Items/InsertSocketPlugFree", 1008 json=body, 1009 auth=access_token, 1010 ) 1011 assert isinstance(resp, dict) 1012 return resp 1013 1014 async def set_item_lock_state( 1015 self, 1016 access_token: str, 1017 state: bool, 1018 /, 1019 item_id: int, 1020 character_id: int, 1021 membership_type: typedefs.IntAnd[enums.MembershipType], 1022 ) -> int: 1023 body = { 1024 "state": state, 1025 "itemId": item_id, 1026 "characterId": character_id, 1027 "membershipType": int(membership_type), 1028 } 1029 response = await self._request( 1030 RequestMethod.POST, 1031 "Destiny2/Actions/Items/SetLockState", 1032 json=body, 1033 auth=access_token, 1034 ) 1035 assert isinstance(response, int) 1036 return response 1037 1038 async def set_quest_track_state( 1039 self, 1040 access_token: str, 1041 state: bool, 1042 /, 1043 item_id: int, 1044 character_id: int, 1045 membership_type: typedefs.IntAnd[enums.MembershipType], 1046 ) -> int: 1047 body = { 1048 "state": state, 1049 "itemId": item_id, 1050 "characterId": character_id, 1051 "membership_type": int(membership_type), 1052 } 1053 response = await self._request( 1054 RequestMethod.POST, 1055 "Destiny2/Actions/Items/SetTrackedState", 1056 json=body, 1057 auth=access_token, 1058 ) 1059 assert isinstance(response, int) 1060 return response 1061 1062 async def fetch_manifest_path(self) -> typedefs.JSONObject: 1063 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1064 path = await self._request(RequestMethod.GET, "Destiny2/Manifest") 1065 assert isinstance(path, dict) 1066 return path 1067 1068 async def read_manifest_bytes(self, language: str = "en", /) -> bytes: 1069 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1070 _ensure_manifest_language(language) 1071 1072 content = await self.fetch_manifest_path() 1073 resp = await self._request( 1074 RequestMethod.GET, 1075 content["mobileWorldContentPaths"][language], 1076 unwrapping="read", 1077 base=True, 1078 ) 1079 assert isinstance(resp, bytes) 1080 return resp 1081 1082 async def download_manifest( 1083 self, 1084 language: str = "en", 1085 name: str = "manifest", 1086 path: typing.Union[pathlib.Path, str] = ".", 1087 *, 1088 force: bool = False, 1089 ) -> None: 1090 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1091 complete_path = _get_path(name, path, sql=True) 1092 1093 if complete_path.exists() and force: 1094 if force: 1095 _LOG.info( 1096 f"Found manifest in {complete_path!s}. Forcing to Re-Download." 1097 ) 1098 complete_path.unlink(missing_ok=True) 1099 1100 return await self.download_manifest(language, name, path, force=force) 1101 1102 else: 1103 raise FileExistsError( 1104 "Manifest file already exists, " 1105 "To force download, set the `force` parameter to `True`." 1106 ) 1107 1108 _LOG.info(f"Downloading manifest. Location: {complete_path!s}") 1109 data_bytes = await self.read_manifest_bytes(language) 1110 await asyncio.get_running_loop().run_in_executor( 1111 None, _write_sqlite_bytes, data_bytes, path, name 1112 ) 1113 1114 async def download_json_manifest( 1115 self, 1116 file_name: str = "manifest", 1117 path: typing.Union[str, pathlib.Path] = ".", 1118 language: str = "en", 1119 ) -> None: 1120 _ensure_manifest_language(language) 1121 1122 _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...") 1123 1124 content = await self.fetch_manifest_path() 1125 json_bytes = await self._request( 1126 RequestMethod.GET, 1127 content["jsonWorldContentPaths"][language], 1128 unwrapping="read", 1129 base=True, 1130 ) 1131 1132 await asyncio.get_running_loop().run_in_executor( 1133 None, _write_json_bytes, json_bytes, file_name, path 1134 ) 1135 _LOG.info("Finished downloading manifest JSON.") 1136 1137 async def fetch_manifest_version(self) -> str: 1138 return typing.cast(str, (await self.fetch_manifest_path())["version"]) 1139 1140 async def fetch_linked_profiles( 1141 self, 1142 member_id: int, 1143 member_type: typedefs.IntAnd[enums.MembershipType], 1144 /, 1145 *, 1146 all: bool = False, 1147 ) -> typedefs.JSONObject: 1148 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1149 resp = await self._request( 1150 RequestMethod.GET, 1151 f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}", 1152 ) 1153 assert isinstance(resp, dict) 1154 return resp 1155 1156 async def fetch_clan_banners(self) -> typedefs.JSONObject: 1157 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1158 resp = await self._request( 1159 RequestMethod.GET, "Destiny2/Clan/ClanBannerDictionary/" 1160 ) 1161 assert isinstance(resp, dict) 1162 return resp 1163 1164 async def fetch_public_milestones(self) -> typedefs.JSONObject: 1165 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1166 resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/") 1167 assert isinstance(resp, dict) 1168 return resp 1169 1170 async def fetch_public_milestone_content( 1171 self, milestone_hash: int, / 1172 ) -> typedefs.JSONObject: 1173 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1174 resp = await self._request( 1175 RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/" 1176 ) 1177 assert isinstance(resp, dict) 1178 return resp 1179 1180 async def fetch_current_user_memberships( 1181 self, access_token: str, / 1182 ) -> typedefs.JSONObject: 1183 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1184 resp = await self._request( 1185 RequestMethod.GET, 1186 "User/GetMembershipsForCurrentUser/", 1187 auth=access_token, 1188 ) 1189 assert isinstance(resp, dict) 1190 return resp 1191 1192 async def equip_item( 1193 self, 1194 access_token: str, 1195 /, 1196 item_id: int, 1197 character_id: int, 1198 membership_type: typedefs.IntAnd[enums.MembershipType], 1199 ) -> None: 1200 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1201 payload = { 1202 "itemId": item_id, 1203 "characterId": character_id, 1204 "membershipType": int(membership_type), 1205 } 1206 1207 await self._request( 1208 RequestMethod.POST, 1209 "Destiny2/Actions/Items/EquipItem/", 1210 json=payload, 1211 auth=access_token, 1212 ) 1213 1214 async def equip_items( 1215 self, 1216 access_token: str, 1217 /, 1218 item_ids: list[int], 1219 character_id: int, 1220 membership_type: typedefs.IntAnd[enums.MembershipType], 1221 ) -> None: 1222 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1223 payload = { 1224 "itemIds": item_ids, 1225 "characterId": character_id, 1226 "membershipType": int(membership_type), 1227 } 1228 await self._request( 1229 RequestMethod.POST, 1230 "Destiny2/Actions/Items/EquipItems/", 1231 json=payload, 1232 auth=access_token, 1233 ) 1234 1235 async def ban_clan_member( 1236 self, 1237 access_token: str, 1238 /, 1239 group_id: int, 1240 membership_id: int, 1241 membership_type: typedefs.IntAnd[enums.MembershipType], 1242 *, 1243 length: int = 0, 1244 comment: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1245 ) -> None: 1246 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1247 payload = {"comment": str(comment), "length": length} 1248 await self._request( 1249 RequestMethod.POST, 1250 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/", 1251 json=payload, 1252 auth=access_token, 1253 ) 1254 1255 async def unban_clan_member( 1256 self, 1257 access_token: str, 1258 /, 1259 group_id: int, 1260 membership_id: int, 1261 membership_type: typedefs.IntAnd[enums.MembershipType], 1262 ) -> None: 1263 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1264 await self._request( 1265 RequestMethod.POST, 1266 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/", 1267 auth=access_token, 1268 ) 1269 1270 async def kick_clan_member( 1271 self, 1272 access_token: str, 1273 /, 1274 group_id: int, 1275 membership_id: int, 1276 membership_type: typedefs.IntAnd[enums.MembershipType], 1277 ) -> typedefs.JSONObject: 1278 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1279 resp = await self._request( 1280 RequestMethod.POST, 1281 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/", 1282 auth=access_token, 1283 ) 1284 assert isinstance(resp, dict) 1285 return resp 1286 1287 async def edit_clan( 1288 self, 1289 access_token: str, 1290 /, 1291 group_id: int, 1292 *, 1293 name: typedefs.NoneOr[str] = None, 1294 about: typedefs.NoneOr[str] = None, 1295 motto: typedefs.NoneOr[str] = None, 1296 theme: typedefs.NoneOr[str] = None, 1297 tags: typedefs.NoneOr[collections.Sequence[str]] = None, 1298 is_public: typedefs.NoneOr[bool] = None, 1299 locale: typedefs.NoneOr[str] = None, 1300 avatar_image_index: typedefs.NoneOr[int] = None, 1301 membership_option: typedefs.NoneOr[ 1302 typedefs.IntAnd[enums.MembershipOption] 1303 ] = None, 1304 allow_chat: typedefs.NoneOr[bool] = None, 1305 chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None, 1306 call_sign: typedefs.NoneOr[str] = None, 1307 homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, 1308 enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None, 1309 default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, 1310 is_public_topic_admin: typedefs.NoneOr[bool] = None, 1311 ) -> None: 1312 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1313 payload = { 1314 "name": name, 1315 "about": about, 1316 "motto": motto, 1317 "theme": theme, 1318 "tags": tags, 1319 "isPublic": is_public, 1320 "avatarImageIndex": avatar_image_index, 1321 "isPublicTopicAdminOnly": is_public_topic_admin, 1322 "allowChat": allow_chat, 1323 "chatSecurity": chat_security, 1324 "callsign": call_sign, 1325 "homepage": homepage, 1326 "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins, 1327 "defaultPublicity": default_publicity, 1328 "locale": locale, 1329 } 1330 if membership_option is not None: 1331 payload["membershipOption"] = int(membership_option) 1332 1333 await self._request( 1334 RequestMethod.POST, 1335 f"GroupV2/{group_id}/Edit", 1336 json=payload, 1337 auth=access_token, 1338 ) 1339 1340 async def edit_clan_options( 1341 self, 1342 access_token: str, 1343 /, 1344 group_id: int, 1345 *, 1346 invite_permissions_override: typedefs.NoneOr[bool] = None, 1347 update_culture_permissionOverride: typedefs.NoneOr[bool] = None, 1348 host_guided_game_permission_override: typedefs.NoneOr[ 1349 typing.Literal[0, 1, 2] 1350 ] = None, 1351 update_banner_permission_override: typedefs.NoneOr[bool] = None, 1352 join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None, 1353 ) -> None: 1354 payload = { 1355 "InvitePermissionOverride": invite_permissions_override, 1356 "UpdateCulturePermissionOverride": update_culture_permissionOverride, 1357 "HostGuidedGamePermissionOverride": host_guided_game_permission_override, 1358 "UpdateBannerPermissionOverride": update_banner_permission_override, 1359 "JoinLevel": int(join_level) if join_level else None, 1360 } 1361 1362 await self._request( 1363 RequestMethod.POST, 1364 f"GroupV2/{group_id}/EditFounderOptions", 1365 json=payload, 1366 auth=access_token, 1367 ) 1368 1369 async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject: 1370 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1371 resp = await self._request( 1372 RequestMethod.GET, 1373 "Social/Friends/", 1374 auth=access_token, 1375 ) 1376 assert isinstance(resp, dict) 1377 return resp 1378 1379 async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject: 1380 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1381 resp = await self._request( 1382 RequestMethod.GET, 1383 "Social/Friends/Requests", 1384 auth=access_token, 1385 ) 1386 assert isinstance(resp, dict) 1387 return resp 1388 1389 async def accept_friend_request(self, access_token: str, /, member_id: int) -> None: 1390 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1391 await self._request( 1392 RequestMethod.POST, 1393 f"Social/Friends/Requests/Accept/{member_id}", 1394 auth=access_token, 1395 ) 1396 1397 async def send_friend_request(self, access_token: str, /, member_id: int) -> None: 1398 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1399 await self._request( 1400 RequestMethod.POST, 1401 f"Social/Friends/Add/{member_id}", 1402 auth=access_token, 1403 ) 1404 1405 async def decline_friend_request( 1406 self, access_token: str, /, member_id: int 1407 ) -> None: 1408 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1409 await self._request( 1410 RequestMethod.POST, 1411 f"Social/Friends/Requests/Decline/{member_id}", 1412 auth=access_token, 1413 ) 1414 1415 async def remove_friend(self, access_token: str, /, member_id: int) -> None: 1416 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1417 await self._request( 1418 RequestMethod.POST, 1419 f"Social/Friends/Remove/{member_id}", 1420 auth=access_token, 1421 ) 1422 1423 async def remove_friend_request(self, access_token: str, /, member_id: int) -> None: 1424 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1425 await self._request( 1426 RequestMethod.POST, 1427 f"Social/Friends/Requests/Remove/{member_id}", 1428 auth=access_token, 1429 ) 1430 1431 async def approve_all_pending_group_users( 1432 self, 1433 access_token: str, 1434 /, 1435 group_id: int, 1436 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1437 ) -> None: 1438 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1439 await self._request( 1440 RequestMethod.POST, 1441 f"GroupV2/{group_id}/Members/ApproveAll", 1442 auth=access_token, 1443 json={"message": str(message)}, 1444 ) 1445 1446 async def deny_all_pending_group_users( 1447 self, 1448 access_token: str, 1449 /, 1450 group_id: int, 1451 *, 1452 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1453 ) -> None: 1454 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1455 await self._request( 1456 RequestMethod.POST, 1457 f"GroupV2/{group_id}/Members/DenyAll", 1458 auth=access_token, 1459 json={"message": str(message)}, 1460 ) 1461 1462 async def add_optional_conversation( 1463 self, 1464 access_token: str, 1465 /, 1466 group_id: int, 1467 *, 1468 name: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1469 security: typing.Literal[0, 1] = 0, 1470 ) -> None: 1471 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1472 payload = {"chatName": str(name), "chatSecurity": security} 1473 await self._request( 1474 RequestMethod.POST, 1475 f"GroupV2/{group_id}/OptionalConversations/Add", 1476 json=payload, 1477 auth=access_token, 1478 ) 1479 1480 async def edit_optional_conversation( 1481 self, 1482 access_token: str, 1483 /, 1484 group_id: int, 1485 conversation_id: int, 1486 *, 1487 name: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1488 security: typing.Literal[0, 1] = 0, 1489 enable_chat: bool = False, 1490 ) -> None: 1491 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1492 payload = { 1493 "chatEnabled": enable_chat, 1494 "chatName": str(name), 1495 "chatSecurity": security, 1496 } 1497 await self._request( 1498 RequestMethod.POST, 1499 f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}", 1500 json=payload, 1501 auth=access_token, 1502 ) 1503 1504 async def transfer_item( 1505 self, 1506 access_token: str, 1507 /, 1508 item_id: int, 1509 item_hash: int, 1510 character_id: int, 1511 member_type: typedefs.IntAnd[enums.MembershipType], 1512 *, 1513 stack_size: int = 1, 1514 vault: bool = False, 1515 ) -> None: 1516 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1517 payload = { 1518 "characterId": character_id, 1519 "membershipType": int(member_type), 1520 "itemId": item_id, 1521 "itemReferenceHash": item_hash, 1522 "stackSize": stack_size, 1523 "transferToVault": vault, 1524 } 1525 await self._request( 1526 RequestMethod.POST, 1527 "Destiny2/Actions/Items/TransferItem", 1528 json=payload, 1529 auth=access_token, 1530 ) 1531 1532 async def pull_item( 1533 self, 1534 access_token: str, 1535 /, 1536 item_id: int, 1537 item_hash: int, 1538 character_id: int, 1539 member_type: typedefs.IntAnd[enums.MembershipType], 1540 *, 1541 stack_size: int = 1, 1542 vault: bool = False, 1543 ) -> None: 1544 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1545 payload = { 1546 "characterId": character_id, 1547 "membershipType": int(member_type), 1548 "itemId": item_id, 1549 "itemReferenceHash": item_hash, 1550 "stackSize": stack_size, 1551 "transferToVault": vault, 1552 } 1553 await self._request( 1554 RequestMethod.POST, 1555 "Destiny2/Actions/Items/PullFromPostmaster", 1556 json=payload, 1557 auth=access_token, 1558 ) 1559 1560 async def fetch_fireteams( 1561 self, 1562 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1563 *, 1564 platform: typedefs.IntAnd[ 1565 fireteams.FireteamPlatform 1566 ] = fireteams.FireteamPlatform.ANY, 1567 language: typing.Union[ 1568 fireteams.FireteamLanguage, str 1569 ] = fireteams.FireteamLanguage.ALL, 1570 date_range: typedefs.IntAnd[ 1571 fireteams.FireteamDate 1572 ] = fireteams.FireteamDate.ALL, 1573 page: int = 0, 1574 slots_filter: int = 0, 1575 ) -> typedefs.JSONObject: 1576 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1577 resp = await self._request( 1578 RequestMethod.GET, 1579 f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}", # noqa: E501 Line too long 1580 ) 1581 assert isinstance(resp, dict) 1582 return resp 1583 1584 async def fetch_avaliable_clan_fireteams( 1585 self, 1586 access_token: str, 1587 group_id: int, 1588 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1589 *, 1590 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1591 language: typing.Union[fireteams.FireteamLanguage, str], 1592 date_range: typedefs.IntAnd[ 1593 fireteams.FireteamDate 1594 ] = fireteams.FireteamDate.ALL, 1595 page: int = 0, 1596 public_only: bool = False, 1597 slots_filter: int = 0, 1598 ) -> typedefs.JSONObject: 1599 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1600 resp = await self._request( 1601 RequestMethod.GET, 1602 f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}", # noqa: E501 1603 json={"langFilter": str(language)}, 1604 auth=access_token, 1605 ) 1606 assert isinstance(resp, dict) 1607 return resp 1608 1609 async def fetch_clan_fireteam( 1610 self, access_token: str, fireteam_id: int, group_id: int 1611 ) -> typedefs.JSONObject: 1612 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1613 resp = await self._request( 1614 RequestMethod.GET, 1615 f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}", 1616 auth=access_token, 1617 ) 1618 assert isinstance(resp, dict) 1619 return resp 1620 1621 async def fetch_my_clan_fireteams( 1622 self, 1623 access_token: str, 1624 group_id: int, 1625 *, 1626 include_closed: bool = True, 1627 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1628 language: typing.Union[fireteams.FireteamLanguage, str], 1629 filtered: bool = True, 1630 page: int = 0, 1631 ) -> typedefs.JSONObject: 1632 payload = {"groupFilter": filtered, "langFilter": str(language)} 1633 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1634 resp = await self._request( 1635 RequestMethod.GET, 1636 f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}", 1637 json=payload, 1638 auth=access_token, 1639 ) 1640 assert isinstance(resp, dict) 1641 return resp 1642 1643 async def fetch_private_clan_fireteams( 1644 self, access_token: str, group_id: int, / 1645 ) -> int: 1646 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1647 resp = await self._request( 1648 RequestMethod.GET, 1649 f"Fireteam/Clan/{group_id}/ActiveCount", 1650 auth=access_token, 1651 ) 1652 assert isinstance(resp, int) 1653 return resp 1654 1655 async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject: 1656 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1657 resp = await self._request( 1658 RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}" 1659 ) 1660 assert isinstance(resp, dict) 1661 return resp 1662 1663 async def search_entities( 1664 self, name: str, entity_type: str, *, page: int = 0 1665 ) -> typedefs.JSONObject: 1666 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1667 resp = await self._request( 1668 RequestMethod.GET, 1669 f"Destiny2/Armory/Search/{entity_type}/{name}/", 1670 json={"page": page}, 1671 ) 1672 assert isinstance(resp, dict) 1673 return resp 1674 1675 async def fetch_unique_weapon_history( 1676 self, 1677 membership_id: int, 1678 character_id: int, 1679 membership_type: typedefs.IntAnd[enums.MembershipType], 1680 ) -> typedefs.JSONObject: 1681 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1682 resp = await self._request( 1683 RequestMethod.GET, 1684 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/", 1685 ) 1686 assert isinstance(resp, dict) 1687 return resp 1688 1689 async def fetch_item( 1690 self, 1691 member_id: int, 1692 item_id: int, 1693 membership_type: typedefs.IntAnd[enums.MembershipType], 1694 components: list[enums.ComponentType], 1695 ) -> typedefs.JSONObject: 1696 collector = _collect_components(components) 1697 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1698 resp = await self._request( 1699 RequestMethod.GET, 1700 f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}", 1701 ) 1702 assert isinstance(resp, dict) 1703 return resp 1704 1705 async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject: 1706 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1707 resp = await self._request( 1708 RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/" 1709 ) 1710 assert isinstance(resp, dict) 1711 return resp 1712 1713 async def fetch_available_locales(self) -> typedefs.JSONObject: 1714 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1715 resp = await self._request( 1716 RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/" 1717 ) 1718 assert isinstance(resp, dict) 1719 return resp 1720 1721 async def fetch_common_settings(self) -> typedefs.JSONObject: 1722 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1723 resp = await self._request(RequestMethod.GET, "Settings") 1724 assert isinstance(resp, dict) 1725 return resp 1726 1727 async def fetch_user_systems_overrides(self) -> typedefs.JSONObject: 1728 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1729 resp = await self._request(RequestMethod.GET, "UserSystemOverrides") 1730 assert isinstance(resp, dict) 1731 return resp 1732 1733 async def fetch_global_alerts( 1734 self, *, include_streaming: bool = False 1735 ) -> typedefs.JSONArray: 1736 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1737 resp = await self._request( 1738 RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}" 1739 ) 1740 assert isinstance(resp, list) 1741 return resp 1742 1743 async def awainitialize_request( 1744 self, 1745 access_token: str, 1746 type: typing.Literal[0, 1], 1747 membership_type: typedefs.IntAnd[enums.MembershipType], 1748 /, 1749 *, 1750 affected_item_id: typing.Optional[int] = None, 1751 character_id: typing.Optional[int] = None, 1752 ) -> typedefs.JSONObject: 1753 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1754 1755 body = {"type": type, "membershipType": int(membership_type)} 1756 1757 if affected_item_id is not None: 1758 body["affectedItemId"] = affected_item_id 1759 1760 if character_id is not None: 1761 body["characterId"] = character_id 1762 1763 resp = await self._request( 1764 RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token 1765 ) 1766 assert isinstance(resp, dict) 1767 return resp 1768 1769 async def awaget_action_token( 1770 self, access_token: str, correlation_id: str, / 1771 ) -> typedefs.JSONObject: 1772 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1773 resp = await self._request( 1774 RequestMethod.POST, 1775 f"Destiny2/Awa/GetActionToken/{correlation_id}", 1776 auth=access_token, 1777 ) 1778 assert isinstance(resp, dict) 1779 return resp 1780 1781 async def awa_provide_authorization_result( 1782 self, 1783 access_token: str, 1784 selection: int, 1785 correlation_id: str, 1786 nonce: collections.MutableSequence[typing.Union[str, bytes]], 1787 ) -> int: 1788 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1789 1790 body = {"selection": selection, "correlationId": correlation_id, "nonce": nonce} 1791 1792 resp = await self._request( 1793 RequestMethod.POST, 1794 "Destiny2/Awa/AwaProvideAuthorizationResult", 1795 json=body, 1796 auth=access_token, 1797 ) 1798 assert isinstance(resp, int) 1799 return resp 1800 1801 async def fetch_vendors( 1802 self, 1803 access_token: str, 1804 character_id: int, 1805 membership_id: int, 1806 membership_type: typedefs.IntAnd[enums.MembershipType], 1807 /, 1808 components: list[enums.ComponentType], 1809 filter: typing.Optional[int] = None, 1810 ) -> typedefs.JSONObject: 1811 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1812 components_ = _collect_components(components) 1813 route = ( 1814 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" 1815 f"/Character/{character_id}/Vendors/?components={components_}" 1816 ) 1817 1818 if filter is not None: 1819 route = route + f"&filter={filter}" 1820 1821 resp = await self._request( 1822 RequestMethod.GET, 1823 route, 1824 auth=access_token, 1825 ) 1826 assert isinstance(resp, dict) 1827 return resp 1828 1829 async def fetch_vendor( 1830 self, 1831 access_token: str, 1832 character_id: int, 1833 membership_id: int, 1834 membership_type: typedefs.IntAnd[enums.MembershipType], 1835 vendor_hash: int, 1836 /, 1837 components: list[enums.ComponentType], 1838 ) -> typedefs.JSONObject: 1839 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1840 components_ = _collect_components(components) 1841 resp = await self._request( 1842 RequestMethod.GET, 1843 ( 1844 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" 1845 f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}" 1846 ), 1847 auth=access_token, 1848 ) 1849 assert isinstance(resp, dict) 1850 return resp 1851 1852 async def fetch_application_api_usage( 1853 self, 1854 access_token: str, 1855 application_id: int, 1856 /, 1857 *, 1858 start: typing.Optional[datetime.datetime] = None, 1859 end: typing.Optional[datetime.datetime] = None, 1860 ) -> typedefs.JSONObject: 1861 end_date, start_date = time.parse_date_range(end, start) 1862 resp = await self._request( 1863 RequestMethod.GET, 1864 f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}", 1865 auth=access_token, 1866 ) 1867 assert isinstance(resp, dict) 1868 return resp 1869 1870 async def fetch_bungie_applications(self) -> typedefs.JSONArray: 1871 resp = await self._request(RequestMethod.GET, "App/FirstParty") 1872 assert isinstance(resp, list) 1873 return resp 1874 1875 async def fetch_content_type(self, type: str, /) -> typedefs.JSONObject: 1876 resp = await self._request(RequestMethod.GET, f"Content/GetContentType/{type}/") 1877 assert isinstance(resp, dict) 1878 return resp 1879 1880 async def fetch_content_by_id( 1881 self, id: int, locale: str, /, *, head: bool = False 1882 ) -> typedefs.JSONObject: 1883 resp = await self._request( 1884 RequestMethod.GET, 1885 f"Content/GetContentById/{id}/{locale}/", 1886 json={"head": head}, 1887 ) 1888 assert isinstance(resp, dict) 1889 return resp 1890 1891 async def fetch_content_by_tag_and_type( 1892 self, locale: str, tag: str, type: str, *, head: bool = False 1893 ) -> typedefs.JSONObject: 1894 resp = await self._request( 1895 RequestMethod.GET, 1896 f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/", 1897 json={"head": head}, 1898 ) 1899 assert isinstance(resp, dict) 1900 return resp 1901 1902 async def search_content_with_text( 1903 self, 1904 locale: str, 1905 /, 1906 content_type: str, 1907 search_text: str, 1908 tag: str, 1909 *, 1910 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1911 source: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1912 ) -> typedefs.JSONObject: 1913 body: typedefs.JSONObject = {} 1914 1915 body["ctype"] = content_type 1916 body["searchtext"] = search_text 1917 body["tag"] = tag 1918 1919 if page is not undefined.UNDEFINED: 1920 body["currentpage"] = page 1921 else: 1922 body["currentpage"] = 1 1923 1924 if source is not undefined.UNDEFINED: 1925 body["source"] = source 1926 else: 1927 source = "" 1928 resp = await self._request( 1929 RequestMethod.GET, f"Content/Search/{locale}/", json=body 1930 ) 1931 assert isinstance(resp, dict) 1932 return resp 1933 1934 async def search_content_by_tag_and_type( 1935 self, 1936 locale: str, 1937 tag: str, 1938 type: str, 1939 *, 1940 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1941 ) -> typedefs.JSONObject: 1942 body: typedefs.JSONObject = {} 1943 body["currentpage"] = 1 if page is undefined.UNDEFINED else page 1944 resp = await self._request( 1945 RequestMethod.GET, 1946 f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/", 1947 json=body, 1948 ) 1949 assert isinstance(resp, dict) 1950 return resp 1951 1952 async def search_help_articles( 1953 self, text: str, size: str, / 1954 ) -> typedefs.JSONObject: 1955 resp = await self._request( 1956 RequestMethod.GET, f"Content/SearchHelpArticles/{text}/{size}/" 1957 ) 1958 assert isinstance(resp, dict) 1959 return resp 1960 1961 async def fetch_topics_page( 1962 self, 1963 category_filter: int, 1964 group: int, 1965 date_filter: int, 1966 sort: typing.Union[str, bytes], 1967 *, 1968 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1969 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.UNDEFINED, 1970 tag_filter: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1971 ) -> typedefs.JSONObject: 1972 body: typedefs.JSONObject = {} 1973 if locales is not undefined.UNDEFINED: 1974 body["locales"] = ",".join(str(locales)) 1975 else: 1976 body["locales"] = ",".join([]) 1977 1978 if tag_filter is not undefined.UNDEFINED: 1979 body["tagstring"] = tag_filter 1980 else: 1981 body["tagstring"] = "" 1982 1983 page = 0 if page is not undefined.UNDEFINED else page 1984 1985 resp = await self._request( 1986 RequestMethod.GET, 1987 f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/", 1988 json=body, 1989 ) 1990 assert isinstance(resp, dict) 1991 return resp 1992 1993 async def fetch_core_topics_page( 1994 self, 1995 category_filter: int, 1996 date_filter: int, 1997 sort: typing.Union[str, bytes], 1998 *, 1999 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 2000 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.UNDEFINED, 2001 ) -> typedefs.JSONObject: 2002 body: typedefs.JSONObject = {} 2003 2004 if locales is not undefined.UNDEFINED: 2005 body["locales"] = ",".join(str(locales)) 2006 else: 2007 body["locales"] = ",".join([]) 2008 2009 resp = await self._request( 2010 RequestMethod.GET, 2011 f"Forum/GetCoreTopicsPaged/{0 if page is undefined.UNDEFINED else page}" 2012 f"/{sort!s}/{date_filter}/{category_filter}/", 2013 json=body, 2014 ) 2015 assert isinstance(resp, dict) 2016 return resp 2017 2018 async def fetch_posts_threaded_page( 2019 self, 2020 parent_post: bool, 2021 page: int, 2022 page_size: int, 2023 parent_post_id: int, 2024 reply_size: int, 2025 root_thread_mode: bool, 2026 sort_mode: int, 2027 show_banned: typing.Optional[str] = None, 2028 ) -> typedefs.JSONObject: 2029 resp = await self._request( 2030 RequestMethod.GET, 2031 f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/" 2032 f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/", 2033 json={"showbanned": show_banned}, 2034 ) 2035 assert isinstance(resp, dict) 2036 return resp 2037 2038 async def fetch_posts_threaded_page_from_child( 2039 self, 2040 child_id: bool, 2041 page: int, 2042 page_size: int, 2043 reply_size: int, 2044 root_thread_mode: bool, 2045 sort_mode: int, 2046 show_banned: typing.Optional[str] = None, 2047 ) -> typedefs.JSONObject: 2048 resp = await self._request( 2049 RequestMethod.GET, 2050 f"Forum/GetPostsThreadedPagedFromChild/{child_id}/" 2051 f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/", 2052 json={"showbanned": show_banned}, 2053 ) 2054 assert isinstance(resp, dict) 2055 return resp 2056 2057 async def fetch_post_and_parent( 2058 self, child_id: int, /, *, show_banned: typing.Optional[str] = None 2059 ) -> typedefs.JSONObject: 2060 resp = await self._request( 2061 RequestMethod.GET, 2062 f"Forum/GetPostAndParent/{child_id}/", 2063 json={"showbanned": show_banned}, 2064 ) 2065 assert isinstance(resp, dict) 2066 return resp 2067 2068 async def fetch_posts_and_parent_awaiting( 2069 self, child_id: int, /, *, show_banned: typing.Optional[str] = None 2070 ) -> typedefs.JSONObject: 2071 resp = await self._request( 2072 RequestMethod.GET, 2073 f"Forum/GetPostAndParentAwaitingApproval/{child_id}/", 2074 json={"showbanned": show_banned}, 2075 ) 2076 assert isinstance(resp, dict) 2077 return resp 2078 2079 async def fetch_topic_for_content(self, content_id: int, /) -> int: 2080 resp = await self._request( 2081 RequestMethod.GET, f"Forum/GetTopicForContent/{content_id}/" 2082 ) 2083 assert isinstance(resp, int) 2084 return resp 2085 2086 async def fetch_forum_tag_suggestions( 2087 self, partial_tag: str, / 2088 ) -> typedefs.JSONObject: 2089 resp = await self._request( 2090 RequestMethod.GET, 2091 "Forum/GetForumTagSuggestions/", 2092 json={"partialtag": partial_tag}, 2093 ) 2094 assert isinstance(resp, dict) 2095 return resp 2096 2097 async def fetch_poll(self, topic_id: int, /) -> typedefs.JSONObject: 2098 resp = await self._request(RequestMethod.GET, f"Forum/Poll/{topic_id}/") 2099 assert isinstance(resp, dict) 2100 return resp 2101 2102 async def fetch_recuirement_thread_summaries(self) -> typedefs.JSONArray: 2103 resp = await self._request(RequestMethod.POST, "Forum/Recruit/Summaries/") 2104 assert isinstance(resp, list) 2105 return resp 2106 2107 async def fetch_recommended_groups( 2108 self, 2109 accecss_token: str, 2110 /, 2111 *, 2112 date_range: int = 0, 2113 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 2114 ) -> typedefs.JSONArray: 2115 resp = await self._request( 2116 RequestMethod.POST, 2117 f"GroupV2/Recommended/{int(group_type)}/{date_range}/", 2118 auth=accecss_token, 2119 ) 2120 assert isinstance(resp, list) 2121 return resp 2122 2123 async def fetch_available_avatars(self) -> collections.Mapping[str, int]: 2124 resp = await self._request(RequestMethod.GET, "GroupV2/GetAvailableAvatars/") 2125 assert isinstance(resp, dict) 2126 return resp 2127 2128 async def fetch_user_clan_invite_setting( 2129 self, 2130 access_token: str, 2131 /, 2132 membership_type: typedefs.IntAnd[enums.MembershipType], 2133 ) -> bool: 2134 resp = await self._request( 2135 RequestMethod.GET, 2136 f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/", 2137 auth=access_token, 2138 ) 2139 assert isinstance(resp, bool) 2140 return resp 2141 2142 async def fetch_banned_group_members( 2143 self, access_token: str, group_id: int, /, *, page: int = 1 2144 ) -> typedefs.JSONObject: 2145 resp = await self._request( 2146 RequestMethod.GET, 2147 f"GroupV2/{group_id}/Banned/?currentpage={page}", 2148 auth=access_token, 2149 ) 2150 assert isinstance(resp, dict) 2151 return resp 2152 2153 async def fetch_pending_group_memberships( 2154 self, access_token: str, group_id: int, /, *, current_page: int = 1 2155 ) -> typedefs.JSONObject: 2156 resp = await self._request( 2157 RequestMethod.GET, 2158 f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}", 2159 auth=access_token, 2160 ) 2161 assert isinstance(resp, dict) 2162 return resp 2163 2164 async def fetch_invited_group_memberships( 2165 self, access_token: str, group_id: int, /, *, current_page: int = 1 2166 ) -> typedefs.JSONObject: 2167 resp = await self._request( 2168 RequestMethod.GET, 2169 f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}", 2170 auth=access_token, 2171 ) 2172 assert isinstance(resp, dict) 2173 return resp 2174 2175 async def invite_member_to_group( 2176 self, 2177 access_token: str, 2178 /, 2179 group_id: int, 2180 membership_id: int, 2181 membership_type: typedefs.IntAnd[enums.MembershipType], 2182 *, 2183 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 2184 ) -> typedefs.JSONObject: 2185 resp = await self._request( 2186 RequestMethod.POST, 2187 f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/", 2188 auth=access_token, 2189 json={"message": str(message)}, 2190 ) 2191 assert isinstance(resp, dict) 2192 return resp 2193 2194 async def cancel_group_member_invite( 2195 self, 2196 access_token: str, 2197 /, 2198 group_id: int, 2199 membership_id: int, 2200 membership_type: typedefs.IntAnd[enums.MembershipType], 2201 ) -> typedefs.JSONObject: 2202 resp = await self._request( 2203 RequestMethod.POST, 2204 f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/", 2205 auth=access_token, 2206 ) 2207 assert isinstance(resp, dict) 2208 return resp 2209 2210 async def fetch_historical_definition(self) -> typedefs.JSONObject: 2211 resp = await self._request(RequestMethod.GET, "Destiny2/Stats/Definition/") 2212 assert isinstance(resp, dict) 2213 return resp 2214 2215 async def fetch_historical_stats( 2216 self, 2217 character_id: int, 2218 membership_id: int, 2219 membership_type: typedefs.IntAnd[enums.MembershipType], 2220 day_start: datetime.datetime, 2221 day_end: datetime.datetime, 2222 groups: list[typedefs.IntAnd[enums.StatsGroupType]], 2223 modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]], 2224 *, 2225 period_type: enums.PeriodType = enums.PeriodType.ALL_TIME, 2226 ) -> typedefs.JSONObject: 2227 end, start = time.parse_date_range(day_end, day_start) 2228 resp = await self._request( 2229 RequestMethod.GET, 2230 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/", 2231 json={ 2232 "dayend": end, 2233 "daystart": start, 2234 "groups": [str(int(group)) for group in groups], 2235 "modes": [str(int(mode)) for mode in modes], 2236 "periodType": int(period_type), 2237 }, 2238 ) 2239 assert isinstance(resp, dict) 2240 return resp 2241 2242 async def fetch_historical_stats_for_account( 2243 self, 2244 membership_id: int, 2245 membership_type: typedefs.IntAnd[enums.MembershipType], 2246 groups: list[typedefs.IntAnd[enums.StatsGroupType]], 2247 ) -> typedefs.JSONObject: 2248 resp = await self._request( 2249 RequestMethod.GET, 2250 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/", 2251 json={"groups": [str(int(group)) for group in groups]}, 2252 ) 2253 assert isinstance(resp, dict) 2254 return resp 2255 2256 async def fetch_aggregated_activity_stats( 2257 self, 2258 character_id: int, 2259 membership_id: int, 2260 membership_type: typedefs.IntAnd[enums.MembershipType], 2261 /, 2262 ) -> typedefs.JSONObject: 2263 resp = await self._request( 2264 RequestMethod.GET, 2265 f"Destiny2/{int(membership_type)}/Account/{membership_id}/" 2266 f"Character/{character_id}/Stats/AggregateActivityStats/", 2267 ) 2268 assert isinstance(resp, dict) 2269 return resp 2270 2271 async def equip_loadout( 2272 self, 2273 access_token: str, 2274 /, 2275 loadout_index: int, 2276 character_id: int, 2277 membership_type: typedefs.IntAnd[enums.MembershipType], 2278 ) -> None: 2279 response = await self._request( 2280 RequestMethod.POST, 2281 "Destiny2/Actions/Loadouts/EquipLoadout/", 2282 json={ 2283 "loadoutIndex": loadout_index, 2284 "characterId": character_id, 2285 "membership_type": int(membership_type), 2286 }, 2287 auth=access_token, 2288 ) 2289 assert isinstance(response, int) 2290 2291 async def snapshot_loadout( 2292 self, 2293 access_token: str, 2294 /, 2295 loadout_index: int, 2296 character_id: int, 2297 membership_type: typedefs.IntAnd[enums.MembershipType], 2298 *, 2299 color_hash: typing.Optional[int] = None, 2300 icon_hash: typing.Optional[int] = None, 2301 name_hash: typing.Optional[int] = None, 2302 ) -> None: 2303 response = await self._request( 2304 RequestMethod.POST, 2305 "Destiny2/Actions/Loadouts/SnapshotLoadout/", 2306 auth=access_token, 2307 json={ 2308 "colorHash": color_hash, 2309 "iconHash": icon_hash, 2310 "nameHash": name_hash, 2311 "loadoutIndex": loadout_index, 2312 "characterId": character_id, 2313 "membershipType": int(membership_type), 2314 }, 2315 ) 2316 assert isinstance(response, int) 2317 2318 async def update_loadout( 2319 self, 2320 access_token: str, 2321 /, 2322 loadout_index: int, 2323 character_id: int, 2324 membership_type: typedefs.IntAnd[enums.MembershipType], 2325 *, 2326 color_hash: typing.Optional[int] = None, 2327 icon_hash: typing.Optional[int] = None, 2328 name_hash: typing.Optional[int] = None, 2329 ) -> None: 2330 response = await self._request( 2331 RequestMethod.POST, 2332 "Destiny2/Actions/Loadouts/UpdateLoadoutIdentifiers/", 2333 auth=access_token, 2334 json={ 2335 "colorHash": color_hash, 2336 "iconHash": icon_hash, 2337 "nameHash": name_hash, 2338 "loadoutIndex": loadout_index, 2339 "characterId": character_id, 2340 "membershipType": int(membership_type), 2341 }, 2342 ) 2343 assert isinstance(response, int) 2344 2345 async def clear_loadout( 2346 self, 2347 access_token: str, 2348 /, 2349 loadout_index: int, 2350 character_id: int, 2351 membership_type: typedefs.IntAnd[enums.MembershipType], 2352 ) -> None: 2353 response = await self._request( 2354 RequestMethod.POST, 2355 "Destiny2/Actions/Loadouts/ClearLoadout/", 2356 json={ 2357 "loadoutIndex": loadout_index, 2358 "characterId": character_id, 2359 "membership_type": int(membership_type), 2360 }, 2361 auth=access_token, 2362 ) 2363 assert isinstance(response, int)
A RESTful client implementation for Bungie's API.
This client is designed to only make HTTP requests and return JSON objects to provide RESTful functionality.
This client is also used within aiobungie.Client which deserialize those returned JSON objects
using the factory into Pythonic data classes objects which provide Python functionality.
Example
import aiobungie
async def main():
async with aiobungie.RESTClient("TOKEN") as rest_client:
req = await rest_client.fetch_clan_members(4389205)
clan_members = req['results']
for member in clan_members:
for k, v in member['destinyUserInfo'].items():
print(k, v)
Parameters
- token (
str): A valid application token from Bungie's developer portal.
Other Parameters
- max_retries (
int): The max retries number to retry if the request hit a5xxstatus code. - client_secret (
typing.Optional[str]): An optional application client secret, This is only needed if you're fetching OAuth2 tokens with this client. - client_id (
typing.Optional[int]): An optional application client id, This is only needed if you're fetching OAuth2 tokens with this client. - enable_debugging (
bool | str): Whether to enable logging responses or not.
Logging Levels
False: This will disable logging.True: This will set the level toDEBUGand enable logging minimal information."TRACE" | TRACE: This will log the response headers along with the minimal information.
371 def __init__( 372 self, 373 token: str, 374 /, 375 *, 376 client_secret: typing.Optional[str] = None, 377 client_id: typing.Optional[int] = None, 378 client_session: typing.Optional[aiohttp.ClientSession] = None, 379 max_retries: int = 4, 380 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, 381 ) -> None: 382 self._session: typing.Optional[aiohttp.ClientSession] = client_session 383 self._lock: typing.Optional[asyncio.Lock] = None 384 self._client_secret = client_secret 385 self._client_id = client_id 386 self._token: str = token 387 self._max_retries = max_retries 388 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} 389 390 self._set_debug_level(enable_debugging)
A mutable mapping storage for the user's needs.
This mapping is useful for storing any kind of data that the user may need.
Example
import aiobungie
client = aiobungie.RESTClient(…)
async with client:
# Fetch auth tokens and store them
client.metadata["tokens"] = await client.fetch_access_token("code")
# Some other time.
async with client:
# Retrieve the tokens
tokens: aiobungie.OAuth2Response = client.metadata["tokens"]
# Use them to fetch your user.
user = await client.fetch_current_user_memberships(tokens.access_token)
404 @typing.final 405 async def close(self) -> None: 406 if self._session is None: 407 raise RuntimeError("REST client is not running.") 408 409 await self._session.close() 410 self._session = None
Close this REST client session if it was acquired.
This method is automatically called when using async with contextmanager.
Raises
RuntimeError: If the client is already closed.
412 @typing.final 413 def open(self) -> None: 414 """Open a new client session. This is called internally with contextmanager usage.""" 415 if self._session: 416 raise RuntimeError("Cannot open REST client when it's already open.") 417 418 self._session = aiohttp.ClientSession( 419 connector=aiohttp.TCPConnector(ssl=False), 420 raise_for_status=False, 421 timeout=aiohttp.ClientTimeout(total=30.0), 422 )
Open a new client session. This is called internally with contextmanager usage.
424 @typing.final 425 def enable_debugging( 426 self, 427 level: typing.Union[typing.Literal["TRACE"], bool, int] = False, 428 file: typing.Optional[typing.Union[pathlib.Path, str]] = None, 429 /, 430 ) -> None: 431 self._set_debug_level(level, file)
Enables debugging for the REST calls.
Logging Levels
False: This will disable logging.True: This will set the level toDEBUGand enable logging minimal information."TRACE"|TRACE: This will log the response headers along with the minimal information.
Parameters
- level (
str | bool | int): The level of debugging to enable. - file (
pathlib.Path | str | None): The file path to write the debug logs to. If provided.
433 @typing.final 434 async def static_request( 435 self, 436 method: typing.Union[RequestMethod, str], 437 path: str, 438 *, 439 auth: typing.Optional[str] = None, 440 json: typing.Optional[dict[str, typing.Any]] = None, 441 ) -> ResponseSig: 442 return await self._request(method, path, auth=auth, json=json)
Perform an HTTP request given a valid Bungie endpoint.
Parameters
- method (
RequestMethod | str): The request method, This may beGET,POST,PUT, etc. - path (
str): The Bungie endpoint or path. A path must look something like thisDestiny2/3/Profile/46111239123/... - auth (
str | None): An optional bearer token for methods that requires OAuth2 Authorization header. - json (
dict[str, typing.Any] | None): An optional JSON data to include in the request.
Returns
aiobungie.rest.ResponseSig: The response payload.
444 @typing.final 445 def build_oauth2_url( 446 self, client_id: typing.Optional[int] = None 447 ) -> typing.Optional[builders.OAuthURL]: 448 client_id = client_id or self._client_id 449 if client_id is None: 450 return None 451 452 return builders.OAuthURL(client_id=client_id)
Builds an OAuth2 URL using the provided user REST/Base client secret/id.
You can't get the complete string URL by using .compile() method.
Parameters
- client_id (
int | None): An optional client id to provide, If leftNoneit will roll back to the id passed to theRESTClient, If both isNonethis method will returnNone.
Returns
aiobungie.builders.OAuthURL | None: If the client id was provided as a parameter or provided inaiobungie.RESTClient, A complete OAuthURL object will be returned. OtherwiseNonewill be returned.
660 async def fetch_oauth2_tokens(self, code: str, /) -> builders.OAuth2Response: 661 if not isinstance(self._client_secret, (str, int)): 662 raise TypeError( 663 "Expected (str, int) for client secret " 664 f"but got {type(self._client_secret).__name__}" # type: ignore 665 ) 666 667 headers = { 668 "client_secret": self._client_secret, 669 } 670 671 data = ( 672 f"grant_type=authorization_code&code={code}" 673 f"&client_id={self._client_id}&client_secret={self._client_secret}" 674 ) 675 676 response = await self._request( 677 RequestMethod.POST, "", headers=headers, data=data, oauth2=True 678 ) 679 assert isinstance(response, dict) 680 return builders.OAuth2Response.build_response(response)
Makes a POST request and fetch the OAuth2 access_token and refresh token.
Parameters
- code (
str): The Authorization code received from the authorization endpoint found in the URL parameters.
Returns
aiobungie.builders.OAuth2Response: An OAuth2 deserialized response.
Raises
Unauthorized: The passed code was invalid.
682 async def refresh_access_token( 683 self, refresh_token: str, / 684 ) -> builders.OAuth2Response: 685 if not isinstance(self._client_secret, (int, str)): 686 raise TypeError( 687 f"Expected (str, int) for client secret but got {type(self._client_secret).__name__}" # type: ignore 688 ) 689 690 data = { 691 "grant_type": "refresh_token", 692 "refresh_token": refresh_token, 693 "client_id": self._client_id, 694 "client_secret": self._client_secret, 695 "Content-Type": "application/x-www-form-urlencoded", 696 } 697 698 response = await self._request(RequestMethod.POST, "", data=data, oauth2=True) 699 assert isinstance(response, dict) 700 return builders.OAuth2Response.build_response(response)
Refresh OAuth2 access token given its refresh token.
Parameters
- refresh_token (
str): The refresh token.
Returns
aiobungie.builders.OAuth2Response: An OAuth2 deserialized response.
702 async def fetch_bungie_user(self, id: int) -> typedefs.JSONObject: 703 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 704 resp = await self._request( 705 RequestMethod.GET, f"User/GetBungieNetUserById/{id}/" 706 ) 707 assert isinstance(resp, dict) 708 return resp
Fetch a Bungie user by their id.
Parameters
- id (
int): The user id.
Returns
aiobungie.typedefs.JSONObject: A JSON object of users objects.
Raises
NotFound: The user was not found.
716 async def fetch_membership_from_id( 717 self, 718 id: int, 719 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 720 /, 721 ) -> typedefs.JSONObject: 722 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 723 resp = await self._request( 724 RequestMethod.GET, f"User/GetMembershipsById/{id}/{int(type)}" 725 ) 726 assert isinstance(resp, dict) 727 return resp
Fetch Bungie user's memberships from their id.
Parameters
- id (
int): The user's id. - type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The user's membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the found user.
Raises
- aiobungie.NotFound: The requested user was not found.
729 async def fetch_player( 730 self, 731 name: str, 732 code: int, 733 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.ALL, 734 /, 735 ) -> typedefs.JSONArray: 736 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 737 resp = await self._request( 738 RequestMethod.POST, 739 f"Destiny2/SearchDestinyPlayerByBungieName/{int(type)}", 740 json={"displayName": name, "displayNameCode": code}, 741 ) 742 assert isinstance(resp, list) 743 return resp
Fetch a Destiny 2 Player.
Parameters
- name (
str): The unique Bungie player name. - code (
int): The unique Bungie display name code. - type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The player's membership type, e,g. XBOX, STEAM, PSN
Returns
aiobungie.typedefs.JSONArray: A JSON array of the found player's memberships.
Raises
aiobungie.NotFound: The player was not found.aiobungie.MembershipTypeError: The provided membership type was invalid.
745 async def search_users(self, name: str, /) -> typedefs.JSONObject: 746 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 747 resp = await self._request( 748 RequestMethod.POST, 749 "User/Search/GlobalName/0", 750 json={"displayNamePrefix": name}, 751 ) 752 assert isinstance(resp, dict) 753 return resp
Search for users by their global name and return all users who share this name.
Parameters
- name (
str): The user name.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of the found users.
Raises
aiobungie.NotFound: The user(s) was not found.
755 async def fetch_clan_from_id( 756 self, id: int, /, access_token: typing.Optional[str] = None 757 ) -> typedefs.JSONObject: 758 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 759 resp = await self._request( 760 RequestMethod.GET, f"GroupV2/{id}", auth=access_token 761 ) 762 assert isinstance(resp, dict) 763 return resp
Fetch a Bungie Clan by its id.
Parameters
- id (
int): The clan id.
Other Parameters
access_token (
typing.Optional[str]): An optional access token to make the request with.If the token was bound to a member of the clan, This field
aiobungie.crates.Clan.current_user_membershipwill be available and will return the membership of the user who made this request.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the clan.
Raises
aiobungie.NotFound: The clan was not found.
765 async def fetch_clan( 766 self, 767 name: str, 768 /, 769 access_token: typing.Optional[str] = None, 770 *, 771 type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 772 ) -> typedefs.JSONObject: 773 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 774 resp = await self._request( 775 RequestMethod.GET, f"GroupV2/Name/{name}/{int(type)}", auth=access_token 776 ) 777 assert isinstance(resp, dict) 778 return resp
Fetch a Clan by its name. This method will return the first clan found with given name name.
Parameters
- name (
str): The clan name.
Other Parameters
access_token (
typing.Optional[str]): An optional access token to make the request with.If the token was bound to a member of the clan, This field
aiobungie.crates.Clan.current_user_membershipwill be available and will return the membership of the user who made this request.- type (
aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group type, Default is one.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the clan.
Raises
aiobungie.NotFound: The clan was not found.
780 async def fetch_clan_admins(self, clan_id: int, /) -> typedefs.JSONObject: 781 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 782 resp = await self._request( 783 RequestMethod.GET, f"GroupV2/{clan_id}/AdminsAndFounder/" 784 ) 785 assert isinstance(resp, dict) 786 return resp
Fetch the admins and founder members of the clan.
Parameters
- clan_id (
int): The clan id.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the clan admins and founder members.
Raises
aiobungie.NotFound: The clan was not found.
788 async def fetch_clan_conversations(self, clan_id: int, /) -> typedefs.JSONArray: 789 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 790 resp = await self._request( 791 RequestMethod.GET, f"GroupV2/{clan_id}/OptionalConversations/" 792 ) 793 assert isinstance(resp, list) 794 return resp
Fetch a clan's conversations.
Parameters
- clan_id (
int): The clan's id.
Returns
aiobungie.typedefs.JSONArray: A JSON array of the conversations.
796 async def fetch_application(self, appid: int, /) -> typedefs.JSONObject: 797 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 798 resp = await self._request(RequestMethod.GET, f"App/Application/{appid}") 799 assert isinstance(resp, dict) 800 return resp
Fetch a Bungie Application.
Parameters
- appid (
int): The application id.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the application.
802 async def fetch_character( 803 self, 804 member_id: int, 805 membership_type: typedefs.IntAnd[enums.MembershipType], 806 character_id: int, 807 components: list[enums.ComponentType], 808 auth: typing.Optional[str] = None, 809 ) -> typedefs.JSONObject: 810 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 811 collector = _collect_components(components) 812 response = await self._request( 813 RequestMethod.GET, 814 f"Destiny2/{int(membership_type)}/Profile/{member_id}/" 815 f"Character/{character_id}/?components={collector}", 816 auth=auth, 817 ) 818 assert isinstance(response, dict) 819 return response
Fetch a Destiny 2 player's characters.
Parameters
- member_id (
int): A valid bungie member id. - membership_type (
aiobungie.typedefs.IntAnd[MembershipType]): The member's membership type. - character_id (
int): The character id to return. - components (
list[aiobungie.ComponentType]): A list of character components to collect and return.
Other Parameters
- auth (
typing.Optional[str]): A bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the requested character.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
821 async def fetch_activities( 822 self, 823 member_id: int, 824 character_id: int, 825 mode: typedefs.IntAnd[enums.GameMode], 826 membership_type: typedefs.IntAnd[ 827 enums.MembershipType 828 ] = enums.MembershipType.ALL, 829 *, 830 page: int = 0, 831 limit: int = 1, 832 ) -> typedefs.JSONObject: 833 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 834 resp = await self._request( 835 RequestMethod.GET, 836 f"Destiny2/{int(membership_type)}/Account/" 837 f"{member_id}/Character/{character_id}/Stats/Activities" 838 f"/?mode={int(mode)}&count={limit}&page={page}", 839 ) 840 assert isinstance(resp, dict) 841 return resp
Fetch a Destiny 2 activity for the specified user id and character.
Parameters
- member_id (
int): The user id that starts with4611. - character_id (
int): The id of the character to retrieve. - mode (
aiobungie.typedefs.IntAnd[aiobungie.GameMode]): This parameter filters the game mode, Nightfall, Strike, Iron Banner, etc.
Other Parameters
- membership_type (
aiobungie.typedefs.IntAnd[MembershipType]): The Member ship type, if nothing was passed than it will return all. - page (
int): The page number. Default to1 - limit (
int): Limit the returned result. Default to1
Returns
aiobungie.typedefs.JSONObject: A JSON object of the player's activities.
Raises
NotFound: The activity was not found.aiobungie.MembershipTypeError: The provided membership type was invalid.
843 async def fetch_vendor_sales(self) -> typedefs.JSONObject: 844 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 845 resp = await self._request( 846 RequestMethod.GET, 847 f"Destiny2/Vendors/?components={int(enums.ComponentType.VENDOR_SALES)}", 848 ) 849 assert isinstance(resp, dict) 850 return resp
852 async def fetch_profile( 853 self, 854 membership_id: int, 855 type: typedefs.IntAnd[enums.MembershipType], 856 components: list[enums.ComponentType], 857 auth: typing.Optional[str] = None, 858 ) -> typedefs.JSONObject: 859 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 860 collector = _collect_components(components) 861 response = await self._request( 862 RequestMethod.GET, 863 f"Destiny2/{int(type)}/Profile/{membership_id}/?components={collector}", 864 auth=auth, 865 ) 866 assert isinstance(response, dict) 867 return response
Fetch a bungie profile.
Parameters
- membership_id (
int): The member's id. - type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): A valid membership type. - components (
list[aiobungie.ComponentType]): A list of profile components to collect and return.
Other Parameters
- auth (
typing.Optional[str]): A bearer access_token to make the request with. This is optional and limited to components that only requires an Authorization token.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the found profile.
Raises
aiobungie.MembershipTypeError: The provided membership type was invalid.
869 async def fetch_entity(self, type: str, hash: int) -> typedefs.JSONObject: 870 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 871 response = await self._request( 872 RequestMethod.GET, route=f"Destiny2/Manifest/{type}/{hash}" 873 ) 874 assert isinstance(response, dict) 875 return response
Fetch a Destiny definition item given its type and hash.
Parameters
- type (
str): Entity's type definition. - hash (
int): Entity's hash.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the definition data.
877 async def fetch_inventory_item(self, hash: int, /) -> typedefs.JSONObject: 878 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 879 resp = await self.fetch_entity("DestinyInventoryItemDefinition", hash) 880 assert isinstance(resp, dict) 881 return resp
Fetch a Destiny inventory item entity given a its hash.
Parameters
- hash (
int): Entity's hash.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the inventory item.
883 async def fetch_objective_entity(self, hash: int, /) -> typedefs.JSONObject: 884 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 885 resp = await self.fetch_entity("DestinyObjectiveDefinition", hash) 886 assert isinstance(resp, dict) 887 return resp
Fetch a Destiny objective entity given a its hash.
Parameters
- hash (
int): objective's hash.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the objetive data.
889 async def fetch_groups_for_member( 890 self, 891 member_id: int, 892 member_type: typedefs.IntAnd[enums.MembershipType], 893 /, 894 *, 895 filter: int = 0, 896 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 897 ) -> typedefs.JSONObject: 898 resp = await self._request( 899 RequestMethod.GET, 900 f"GroupV2/User/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", 901 ) 902 assert isinstance(resp, dict) 903 return resp
Fetch the information about the groups for a member.
Parameters
- member_id (
int): The member's id - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Other Parameters
- filter (
builsins.int): Filter apply to list of joined groups. This Default to0 - group_type (
aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. This is always set toaiobungie.GroupType.CLANand should not be changed.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of the member's membership data and groups data.
905 async def fetch_potential_groups_for_member( 906 self, 907 member_id: int, 908 member_type: typedefs.IntAnd[enums.MembershipType], 909 /, 910 *, 911 filter: int = 0, 912 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 913 ) -> typedefs.JSONObject: 914 resp = await self._request( 915 RequestMethod.GET, 916 f"GroupV2/User/Potential/{int(member_type)}/{member_id}/{filter}/{int(group_type)}/", 917 ) 918 assert isinstance(resp, dict) 919 return resp
Get information about the groups that a given member has applied to or been invited to.
Parameters
- member_id (
int): The member's id - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Other Parameters
- filter (
builsins.int): Filter apply to list of joined groups. This Default to0 - group_type (
aiobungie.typedefs.IntAnd[aiobungie.GroupType]): The group's type. This is always set toaiobungie.GroupType.CLANand should not be changed.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of the member's membership data and groups data.
921 async def fetch_clan_members( 922 self, 923 clan_id: int, 924 /, 925 *, 926 name: typing.Optional[str] = None, 927 type: typedefs.IntAnd[enums.MembershipType] = enums.MembershipType.NONE, 928 ) -> typedefs.JSONObject: 929 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 930 resp = await self._request( 931 RequestMethod.GET, 932 f"/GroupV2/{clan_id}/Members/?memberType={int(type)}&nameSearch={name if name else ''}¤tpage=1", 933 ) 934 assert isinstance(resp, dict) 935 return resp
Fetch all Bungie Clan members.
Parameters
- clan_id (
builsins.int): The clans id
Other Parameters
- name (
typing.Optional[str]): If provided, Only players matching this name will be returned. - type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): An optional clan member's membership type. Default is set toaiobungie.MembershipType.NONEWhich returns the first matched clan member by their name.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of clan members.
Raises
aiobungie.NotFound: The clan was not found.
937 async def fetch_hardlinked_credentials( 938 self, 939 credential: int, 940 type: typedefs.IntAnd[enums.CredentialType] = enums.CredentialType.STEAMID, 941 /, 942 ) -> typedefs.JSONObject: 943 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 944 resp = await self._request( 945 RequestMethod.GET, 946 f"User/GetMembershipFromHardLinkedCredential/{int(type)}/{credential}/", 947 ) 948 assert isinstance(resp, dict) 949 return resp
Gets any hard linked membership given a credential.
Only works for credentials that are public just aiobungie.CredentialType.STEAMID right now.
Cross Save aware.
Parameters
- credential (
int): A valid SteamID64 - type (
aiobungie.typedefs.IntAnd[aiobungie.CredentialType]): The crededntial type. This must not be changed Since its only credential that works "currently"
Returns
aiobungie.typedefs.JSONObject: A JSON object of the found user hard linked types.
951 async def fetch_user_credentials( 952 self, access_token: str, membership_id: int, / 953 ) -> typedefs.JSONArray: 954 resp = await self._request( 955 RequestMethod.GET, 956 f"User/GetCredentialTypesForTargetAccount/{membership_id}", 957 auth=access_token, 958 ) 959 assert isinstance(resp, list) 960 return resp
Fetch an array of credential types attached to the requested account.
This method require OAuth2 Bearer access token.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - membership_id (
int): The id of the membership to return.
Returns
aiobungie.typedefs.JSONArray: A JSON array of the returned credentials.
Raises
aiobungie.Unauthorized: The access token was wrong or no access token passed.
962 async def insert_socket_plug( 963 self, 964 action_token: str, 965 /, 966 instance_id: int, 967 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], 968 character_id: int, 969 membership_type: typedefs.IntAnd[enums.MembershipType], 970 ) -> typedefs.JSONObject: 971 if isinstance(plug, builders.PlugSocketBuilder): 972 plug = plug.collect() 973 974 body = { 975 "actionToken": action_token, 976 "itemInstanceId": instance_id, 977 "plug": plug, 978 "characterId": character_id, 979 "membershipType": int(membership_type), 980 } 981 resp = await self._request( 982 RequestMethod.POST, "Destiny2/Actions/Items/InsertSocketPlug", json=body 983 ) 984 assert isinstance(resp, dict) 985 return resp
Insert a plug into a socketed item.
OAuth2: AdvancedWriteActions scope is required
Parameters
- action_token (
str): Action token provided by the AwaGetActionToken API call. - instance_id (
int): The item instance id that's plug inserted. - plug (
typing.Union[aiobungie.builders.PlugSocketBuilder, dict[str, int]]): Either a PlugSocketBuilder object or a raw dict contains key, value for the plug entries.
Example
plug = (
aiobungie.PlugSocketBuilder()
.set_socket_array(0)
.set_socket_index(0)
.set_plug_item(3023847)
.collect()
)
await insert_socket_plug_free(..., plug=plug)
character_id : int
The character's id.
membership_type : aiobungie.typedefs.IntAnd[aiobungie.MembershipType]
The membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains the changed item details.
Raises
aiobungie.Unauthorized: The access token was wrong or no access token passed.
987 async def insert_socket_plug_free( 988 self, 989 access_token: str, 990 /, 991 instance_id: int, 992 plug: typing.Union[builders.PlugSocketBuilder, dict[str, int]], 993 character_id: int, 994 membership_type: typedefs.IntAnd[enums.MembershipType], 995 ) -> typedefs.JSONObject: 996 if isinstance(plug, builders.PlugSocketBuilder): 997 plug = plug.collect() 998 999 body = { 1000 "itemInstanceId": instance_id, 1001 "plug": plug, 1002 "characterId": character_id, 1003 "membershipType": int(membership_type), 1004 } 1005 resp = await self._request( 1006 RequestMethod.POST, 1007 "Destiny2/Actions/Items/InsertSocketPlugFree", 1008 json=body, 1009 auth=access_token, 1010 ) 1011 assert isinstance(resp, dict) 1012 return resp
Insert a plug into a socketed item. This doesn't require an Action token.
OAuth2: MoveEquipDestinyItems scope is required
Parameters
- instance_id (
int): The item instance id that's plug inserted. - plug (
typing.Union[aiobungie.builders.PlugSocketBuilder, dict[str, int]]): Either a PlugSocketBuilder object or a raw dict contains key, value for the plug entries.
Example
plug = (
aiobungie.PlugSocketBuilder()
.set_socket_array(0)
.set_socket_index(0)
.set_plug_item(3023847)
.collect()
)
await insert_socket_plug_free(..., plug=plug)
character_id : int
The character's id.
membership_type : aiobungie.typedefs.IntAnd[aiobungie.MembershipType]
The membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains the changed item details.
Raises
aiobungie.Unauthorized: The access token was wrong or no access token passed.
1014 async def set_item_lock_state( 1015 self, 1016 access_token: str, 1017 state: bool, 1018 /, 1019 item_id: int, 1020 character_id: int, 1021 membership_type: typedefs.IntAnd[enums.MembershipType], 1022 ) -> int: 1023 body = { 1024 "state": state, 1025 "itemId": item_id, 1026 "characterId": character_id, 1027 "membershipType": int(membership_type), 1028 } 1029 response = await self._request( 1030 RequestMethod.POST, 1031 "Destiny2/Actions/Items/SetLockState", 1032 json=body, 1033 auth=access_token, 1034 ) 1035 assert isinstance(response, int) 1036 return response
Set the Lock State for an instanced item.
OAuth2: MoveEquipDestinyItems scope is required
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - state (
bool): IfTrue, The item will be locked, IfFalse, The item will be unlocked. - item_id (
int): The item id. - character_id (
int): The character id. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type for the associated account.
Returns
int: An integer represents whether the request was successful or failed.
Raises
aiobungie.Unauthorized: - The access token was wrong- No access token passed.
- Other authorization causes.
1038 async def set_quest_track_state( 1039 self, 1040 access_token: str, 1041 state: bool, 1042 /, 1043 item_id: int, 1044 character_id: int, 1045 membership_type: typedefs.IntAnd[enums.MembershipType], 1046 ) -> int: 1047 body = { 1048 "state": state, 1049 "itemId": item_id, 1050 "characterId": character_id, 1051 "membership_type": int(membership_type), 1052 } 1053 response = await self._request( 1054 RequestMethod.POST, 1055 "Destiny2/Actions/Items/SetTrackedState", 1056 json=body, 1057 auth=access_token, 1058 ) 1059 assert isinstance(response, int) 1060 return response
Set the Tracking State for an instanced Quest or Bounty.
OAuth2: MoveEquipDestinyItems scope is required
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - state (
bool): IfTrue, The item will be locked, IfFalse, The item will be unlocked. - item_id (
int): The item id. - character_id (
int): The character id. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type for the associated account.
Returns
int: An integer represents whether the request was successful or failed.
Raises
aiobungie.Unauthorized: - The access token was wrong- No access token passed.
- Other authorization causes.
1062 async def fetch_manifest_path(self) -> typedefs.JSONObject: 1063 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1064 path = await self._request(RequestMethod.GET, "Destiny2/Manifest") 1065 assert isinstance(path, dict) 1066 return path
Fetch the manifest JSON paths.
Returns
typedefs.JSONObject: The manifest JSON paths.
1068 async def read_manifest_bytes(self, language: str = "en", /) -> bytes: 1069 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1070 _ensure_manifest_language(language) 1071 1072 content = await self.fetch_manifest_path() 1073 resp = await self._request( 1074 RequestMethod.GET, 1075 content["mobileWorldContentPaths"][language], 1076 unwrapping="read", 1077 base=True, 1078 ) 1079 assert isinstance(resp, bytes) 1080 return resp
Read raw manifest SQLite database bytes response.
This method can be used to write the bytes to zipped file and then extract it to get the manifest content.
Parameters
- language (
str): The manifest database language bytes to get.
Returns
bytes: The bytes to read and write the manifest database.
1082 async def download_manifest( 1083 self, 1084 language: str = "en", 1085 name: str = "manifest", 1086 path: typing.Union[pathlib.Path, str] = ".", 1087 *, 1088 force: bool = False, 1089 ) -> None: 1090 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1091 complete_path = _get_path(name, path, sql=True) 1092 1093 if complete_path.exists() and force: 1094 if force: 1095 _LOG.info( 1096 f"Found manifest in {complete_path!s}. Forcing to Re-Download." 1097 ) 1098 complete_path.unlink(missing_ok=True) 1099 1100 return await self.download_manifest(language, name, path, force=force) 1101 1102 else: 1103 raise FileExistsError( 1104 "Manifest file already exists, " 1105 "To force download, set the `force` parameter to `True`." 1106 ) 1107 1108 _LOG.info(f"Downloading manifest. Location: {complete_path!s}") 1109 data_bytes = await self.read_manifest_bytes(language) 1110 await asyncio.get_running_loop().run_in_executor( 1111 None, _write_sqlite_bytes, data_bytes, path, name 1112 )
A helper method to download the manifest.
Note
This method downloads the sqlite database and not JSON.
Use RESTInterface.download_json_manifest for the JSON version.
Parameters
- language (
str): The manifest language to download, Default is english. - path (
str|pathlib.Path): The path to save the manifest sqlite database. Example"D:/", Default is the current directory. - name (
str): The manifest database file name. Default ismanifest - force (
bool): Whether to force the download. Default isFalse. However if set to true the old file will get removed and a new one will being to download.
Returns
None
Raises
FileNotFoundError: If the manifest file exists andforceisFalse.ValueError: If the provided language was not recognized.
1114 async def download_json_manifest( 1115 self, 1116 file_name: str = "manifest", 1117 path: typing.Union[str, pathlib.Path] = ".", 1118 language: str = "en", 1119 ) -> None: 1120 _ensure_manifest_language(language) 1121 1122 _LOG.info(f"Downloading manifest JSON to {_get_path(file_name, path)!r}...") 1123 1124 content = await self.fetch_manifest_path() 1125 json_bytes = await self._request( 1126 RequestMethod.GET, 1127 content["jsonWorldContentPaths"][language], 1128 unwrapping="read", 1129 base=True, 1130 ) 1131 1132 await asyncio.get_running_loop().run_in_executor( 1133 None, _write_json_bytes, json_bytes, file_name, path 1134 ) 1135 _LOG.info("Finished downloading manifest JSON.")
Download the Bungie manifest json file.
Parameters
- file_name (
str): The file name to save the manifest json file. Default ismanifest. - path (
str|pathlib.Path): The path to save the manifest json file. Default is the current directory. Example"D:/" - language (
str): The manifest database language bytes to get. Default is English.
1137 async def fetch_manifest_version(self) -> str: 1138 return typing.cast(str, (await self.fetch_manifest_path())["version"])
Fetch the manifest version.
Returns
str: The manifest version.
1140 async def fetch_linked_profiles( 1141 self, 1142 member_id: int, 1143 member_type: typedefs.IntAnd[enums.MembershipType], 1144 /, 1145 *, 1146 all: bool = False, 1147 ) -> typedefs.JSONObject: 1148 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1149 resp = await self._request( 1150 RequestMethod.GET, 1151 f"Destiny2/{int(member_type)}/Profile/{member_id}/LinkedProfiles/?getAllMemberships={all}", 1152 ) 1153 assert isinstance(resp, dict) 1154 return resp
Returns a summary information about all profiles linked to the requested member.
The passed membership id/type maybe a Bungie.Net membership or a Destiny memberships.
It will only return linked accounts whose linkages you are allowed to view.
Parameters
- member_id (
int): The ID of the membership. This must be a valid Bungie.Net or PSN or Xbox ID. - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The type for the membership whose linked Destiny account you want to return.
Other Parameters
all (
bool): If provided and set toTrue, All memberships regardless of whether thry're obscured by overrides will be returned,If provided and set to
False, Only available memberships will be returned. The default for this isFalse.
Returns
aiobungie.typedefs.JSONObject- A JSON object which contains an Array of profiles, an Array of profiles with errors and Bungie.Net membership
1164 async def fetch_public_milestones(self) -> typedefs.JSONObject: 1165 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1166 resp = await self._request(RequestMethod.GET, "Destiny2/Milestones/") 1167 assert isinstance(resp, dict) 1168 return resp
Fetch the available milestones.
Returns
aiobungie.typedefs.JSONObject: A JSON object of information about the milestones.
1170 async def fetch_public_milestone_content( 1171 self, milestone_hash: int, / 1172 ) -> typedefs.JSONObject: 1173 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1174 resp = await self._request( 1175 RequestMethod.GET, f"Destiny2/Milestones/{milestone_hash}/Content/" 1176 ) 1177 assert isinstance(resp, dict) 1178 return resp
Fetch the milestone content given its hash.
Parameters
- milestone_hash (
int): The milestone hash.
Returns
aiobungie.typedefs.JSONObject: A JSON object of information related to the fetched milestone.
1180 async def fetch_current_user_memberships( 1181 self, access_token: str, / 1182 ) -> typedefs.JSONObject: 1183 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1184 resp = await self._request( 1185 RequestMethod.GET, 1186 "User/GetMembershipsForCurrentUser/", 1187 auth=access_token, 1188 ) 1189 assert isinstance(resp, dict) 1190 return resp
Fetch a bungie user's accounts with the signed in user. This GET method requires a Bearer access token for the authorization.
This requires OAuth2 scope enabled and the valid Bearer access_token.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the bungie net user and destiny memberships of this account.
1192 async def equip_item( 1193 self, 1194 access_token: str, 1195 /, 1196 item_id: int, 1197 character_id: int, 1198 membership_type: typedefs.IntAnd[enums.MembershipType], 1199 ) -> None: 1200 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1201 payload = { 1202 "itemId": item_id, 1203 "characterId": character_id, 1204 "membershipType": int(membership_type), 1205 } 1206 1207 await self._request( 1208 RequestMethod.POST, 1209 "Destiny2/Actions/Items/EquipItem/", 1210 json=payload, 1211 auth=access_token, 1212 )
Equip an item to a character.
This requires the OAuth2: MoveEquipDestinyItems scope. Also You must have a valid Destiny account, and either be in a social space, in orbit or offline.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - item_id (
int): The item id. - character_id (
int): The character's id to equip the item to. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type assocaiated with this player.
1214 async def equip_items( 1215 self, 1216 access_token: str, 1217 /, 1218 item_ids: list[int], 1219 character_id: int, 1220 membership_type: typedefs.IntAnd[enums.MembershipType], 1221 ) -> None: 1222 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1223 payload = { 1224 "itemIds": item_ids, 1225 "characterId": character_id, 1226 "membershipType": int(membership_type), 1227 } 1228 await self._request( 1229 RequestMethod.POST, 1230 "Destiny2/Actions/Items/EquipItems/", 1231 json=payload, 1232 auth=access_token, 1233 )
Equip multiple items to a character.
This requires the OAuth2: MoveEquipDestinyItems scope. Also You must have a valid Destiny account, and either be in a social space, in orbit or offline.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - item_ids (
list[int]): A list of item ids. - character_id (
int): The character's id to equip the item to. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type assocaiated with this player.
1235 async def ban_clan_member( 1236 self, 1237 access_token: str, 1238 /, 1239 group_id: int, 1240 membership_id: int, 1241 membership_type: typedefs.IntAnd[enums.MembershipType], 1242 *, 1243 length: int = 0, 1244 comment: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1245 ) -> None: 1246 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1247 payload = {"comment": str(comment), "length": length} 1248 await self._request( 1249 RequestMethod.POST, 1250 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Ban/", 1251 json=payload, 1252 auth=access_token, 1253 )
Bans a member from the clan.
This request requires OAuth2: oauth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id. - membership_id (
int): The member id to ban. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Other Parameters
- length (
int): An optional ban length. - comment (
aiobungie.UndefinedOr[str]): An optional comment to this ban. Default isUNDEFINED
1255 async def unban_clan_member( 1256 self, 1257 access_token: str, 1258 /, 1259 group_id: int, 1260 membership_id: int, 1261 membership_type: typedefs.IntAnd[enums.MembershipType], 1262 ) -> None: 1263 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1264 await self._request( 1265 RequestMethod.POST, 1266 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Unban/", 1267 auth=access_token, 1268 )
Unbans a member from the clan.
This request requires OAuth2: oauth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id. - membership_id (
int): The member id to unban. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
1270 async def kick_clan_member( 1271 self, 1272 access_token: str, 1273 /, 1274 group_id: int, 1275 membership_id: int, 1276 membership_type: typedefs.IntAnd[enums.MembershipType], 1277 ) -> typedefs.JSONObject: 1278 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1279 resp = await self._request( 1280 RequestMethod.POST, 1281 f"GroupV2/{group_id}/Members/{int(membership_type)}/{membership_id}/Kick/", 1282 auth=access_token, 1283 ) 1284 assert isinstance(resp, dict) 1285 return resp
Kick a member from the clan.
This request requires OAuth2: oauth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id. - membership_id (
int): The member id to kick. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The member's membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the group that the member has been kicked from.
1287 async def edit_clan( 1288 self, 1289 access_token: str, 1290 /, 1291 group_id: int, 1292 *, 1293 name: typedefs.NoneOr[str] = None, 1294 about: typedefs.NoneOr[str] = None, 1295 motto: typedefs.NoneOr[str] = None, 1296 theme: typedefs.NoneOr[str] = None, 1297 tags: typedefs.NoneOr[collections.Sequence[str]] = None, 1298 is_public: typedefs.NoneOr[bool] = None, 1299 locale: typedefs.NoneOr[str] = None, 1300 avatar_image_index: typedefs.NoneOr[int] = None, 1301 membership_option: typedefs.NoneOr[ 1302 typedefs.IntAnd[enums.MembershipOption] 1303 ] = None, 1304 allow_chat: typedefs.NoneOr[bool] = None, 1305 chat_security: typedefs.NoneOr[typing.Literal[0, 1]] = None, 1306 call_sign: typedefs.NoneOr[str] = None, 1307 homepage: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, 1308 enable_invite_messaging_for_admins: typedefs.NoneOr[bool] = None, 1309 default_publicity: typedefs.NoneOr[typing.Literal[0, 1, 2]] = None, 1310 is_public_topic_admin: typedefs.NoneOr[bool] = None, 1311 ) -> None: 1312 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1313 payload = { 1314 "name": name, 1315 "about": about, 1316 "motto": motto, 1317 "theme": theme, 1318 "tags": tags, 1319 "isPublic": is_public, 1320 "avatarImageIndex": avatar_image_index, 1321 "isPublicTopicAdminOnly": is_public_topic_admin, 1322 "allowChat": allow_chat, 1323 "chatSecurity": chat_security, 1324 "callsign": call_sign, 1325 "homepage": homepage, 1326 "enableInvitationMessagingForAdmins": enable_invite_messaging_for_admins, 1327 "defaultPublicity": default_publicity, 1328 "locale": locale, 1329 } 1330 if membership_option is not None: 1331 payload["membershipOption"] = int(membership_option) 1332 1333 await self._request( 1334 RequestMethod.POST, 1335 f"GroupV2/{group_id}/Edit", 1336 json=payload, 1337 auth=access_token, 1338 )
Edit a clan.
Notes
- This request requires OAuth2: oauth2:
AdminGroupsscope. - All arguments will default to
Noneif not provided. This does not includeaccess_tokenandgroup_id
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id to edit.
Other Parameters
- name (
aiobungie.typedefs.NoneOr[str]): The name to edit the clan with. - about (
aiobungie.typedefs.NoneOr[str]): The about section to edit the clan with. - motto (
aiobungie.typedefs.NoneOr[str]): The motto section to edit the clan with. - theme (
aiobungie.typedefs.NoneOr[str]): The theme name to edit the clan with. - tags (
aiobungie.typedefs.NoneOr[collections.Sequence[str]]): A sequence of strings to replace the clan tags with. - is_public (
aiobungie.typedefs.NoneOr[bool]): If provided and set toTrue, The clan will set to private. If provided and set toFalse, The clan will set to public whether it was or not. - locale (
aiobungie.typedefs.NoneOr[str]): The locale section to edit the clan with. - avatar_image_index (
aiobungie.typedefs.NoneOr[int]): The clan avatar image index to edit the clan with. - membership_option :
aiobungie.typedefs.NoneOr[aiobungie.typedefs.IntAnd[aiobungie.MembershipOption]]# noqa (E501 # Line too long): The clan membership option to edit it with. - allow_chat (
aiobungie.typedefs.NoneOr[bool]): If provided and set toTrue, The clan members will be allowed to chat. If provided and set toFalse, The clan members will not be allowed to chat. - chat_security (
aiobungie.typedefs.NoneOr[typing.Literal[0, 1]]): If provided and set to0, The clan chat security will be edited toGrouponly. If provided and set to1, The clan chat security will be edited toAdminonly. - call_sign (
aiobungie.typedefs.NoneOr[str]): The clan call sign to edit it with. - homepage (
aiobungie.typedefs.NoneOr[typing.Literal[0, 1, 2]]): If provided and set to0, The clan chat homepage will be edited toWall. If provided and set to1, The clan chat homepage will be edited toForum. If provided and set to0, The clan chat homepage will be edited toAllianceForum. - enable_invite_messaging_for_admins (
aiobungie.typedefs.NoneOr[bool]): ??? - default_publicity (
aiobungie.typedefs.NoneOr[typing.Literal[0, 1, 2]]): If provided and set to0, The clan chat publicity will be edited toPublic. If provided and set to1, The clan chat publicity will be edited toAlliance. If provided and set to2, The clan chat publicity will be edited toPrivate. - is_public_topic_admin (
aiobungie.typedefs.NoneOr[bool]): ???
1340 async def edit_clan_options( 1341 self, 1342 access_token: str, 1343 /, 1344 group_id: int, 1345 *, 1346 invite_permissions_override: typedefs.NoneOr[bool] = None, 1347 update_culture_permissionOverride: typedefs.NoneOr[bool] = None, 1348 host_guided_game_permission_override: typedefs.NoneOr[ 1349 typing.Literal[0, 1, 2] 1350 ] = None, 1351 update_banner_permission_override: typedefs.NoneOr[bool] = None, 1352 join_level: typedefs.NoneOr[typedefs.IntAnd[enums.ClanMemberType]] = None, 1353 ) -> None: 1354 payload = { 1355 "InvitePermissionOverride": invite_permissions_override, 1356 "UpdateCulturePermissionOverride": update_culture_permissionOverride, 1357 "HostGuidedGamePermissionOverride": host_guided_game_permission_override, 1358 "UpdateBannerPermissionOverride": update_banner_permission_override, 1359 "JoinLevel": int(join_level) if join_level else None, 1360 } 1361 1362 await self._request( 1363 RequestMethod.POST, 1364 f"GroupV2/{group_id}/EditFounderOptions", 1365 json=payload, 1366 auth=access_token, 1367 )
Edit the clan options.
Notes
- This request requires OAuth2: oauth2:
AdminGroupsscope. - All arguments will default to
Noneif not provided. This does not includeaccess_tokenandgroup_id
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group id.
Other Parameters
- invite_permissions_override (
aiobungie.typedefs.NoneOr[bool]): Minimum Member Level allowed to invite new members to group Always Allowed: Founder, Acting Founder True means admins have this power, false means they don't Default is False for clans, True for groups. - update_culture_permissionOverride (
aiobungie.typedefs.NoneOr[bool]): Minimum Member Level allowed to update group culture Always Allowed: Founder, Acting Founder True means admins have this power, false means they don't Default is False for clans, True for groups. - host_guided_game_permission_override (
aiobungie.typedefs.NoneOr[typing.Literal[0, 1, 2]]): Minimum Member Level allowed to host guided games Always Allowed: Founder, Acting Founder, Admin Allowed Overrides:0-> None,1-> Beginner2-> Member. Default is Member for clans, None for groups, although this means nothing for groups. - update_banner_permission_override (
aiobungie.typedefs.NoneOr[bool]): Minimum Member Level allowed to update banner Always Allowed: Founder, Acting Founder True means admins have this power, false means they don't Default is False for clans, True for groups. - join_level (
aiobungie.ClanMemberType): Level to join a member at when accepting an invite, application, or joining an open clan. Default isaiobungie.ClanMemberType.BEGINNER
1369 async def fetch_friends(self, access_token: str, /) -> typedefs.JSONObject: 1370 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1371 resp = await self._request( 1372 RequestMethod.GET, 1373 "Social/Friends/", 1374 auth=access_token, 1375 ) 1376 assert isinstance(resp, dict) 1377 return resp
Fetch bungie friend list.
This requests OAuth2: ReadUserData scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
aiobungie.typedefs.JSONObject: A JSON object of an array of the bungie friends's data.
1379 async def fetch_friend_requests(self, access_token: str, /) -> typedefs.JSONObject: 1380 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1381 resp = await self._request( 1382 RequestMethod.GET, 1383 "Social/Friends/Requests", 1384 auth=access_token, 1385 ) 1386 assert isinstance(resp, dict) 1387 return resp
Fetch pending bungie friend requests queue.
This requests OAuth2: ReadUserData scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account.
Returns
aiobungie.typedefs.JSONObject: A JSON object of incoming requests and outgoing requests.
1389 async def accept_friend_request(self, access_token: str, /, member_id: int) -> None: 1390 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1391 await self._request( 1392 RequestMethod.POST, 1393 f"Social/Friends/Requests/Accept/{member_id}", 1394 auth=access_token, 1395 )
Accepts a friend relationship with the target user. The user must be on your incoming friend request list.
This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to accept.
1397 async def send_friend_request(self, access_token: str, /, member_id: int) -> None: 1398 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1399 await self._request( 1400 RequestMethod.POST, 1401 f"Social/Friends/Add/{member_id}", 1402 auth=access_token, 1403 )
Requests a friend relationship with the target user.
This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to send the request to.
1405 async def decline_friend_request( 1406 self, access_token: str, /, member_id: int 1407 ) -> None: 1408 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1409 await self._request( 1410 RequestMethod.POST, 1411 f"Social/Friends/Requests/Decline/{member_id}", 1412 auth=access_token, 1413 )
Decline a friend request with the target user. The user must be in your incoming friend request list.
This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to decline.
1415 async def remove_friend(self, access_token: str, /, member_id: int) -> None: 1416 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1417 await self._request( 1418 RequestMethod.POST, 1419 f"Social/Friends/Remove/{member_id}", 1420 auth=access_token, 1421 )
Removes a friend from your friend list. The user must be in your friend list.
This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to remove.
1423 async def remove_friend_request(self, access_token: str, /, member_id: int) -> None: 1424 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1425 await self._request( 1426 RequestMethod.POST, 1427 f"Social/Friends/Requests/Remove/{member_id}", 1428 auth=access_token, 1429 )
Removes a friend from your friend list requests. The user must be in your outgoing request list.
.. note : This request requires OAuth2: BnetWrite scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - member_id (
int): The member's id to remove from the requested friend list.
1431 async def approve_all_pending_group_users( 1432 self, 1433 access_token: str, 1434 /, 1435 group_id: int, 1436 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1437 ) -> None: 1438 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1439 await self._request( 1440 RequestMethod.POST, 1441 f"GroupV2/{group_id}/Members/ApproveAll", 1442 auth=access_token, 1443 json={"message": str(message)}, 1444 )
Approve all pending users for the given group id.
This request requires OAuth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The given group id.
Other Parameters
- message (
aiobungie.UndefinedOr[str]): An optional message to send with the request. Default isUNDEFINED.
1446 async def deny_all_pending_group_users( 1447 self, 1448 access_token: str, 1449 /, 1450 group_id: int, 1451 *, 1452 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1453 ) -> None: 1454 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1455 await self._request( 1456 RequestMethod.POST, 1457 f"GroupV2/{group_id}/Members/DenyAll", 1458 auth=access_token, 1459 json={"message": str(message)}, 1460 )
Deny all pending users for the given group id.
This request requires OAuth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The given group id.
Other Parameters
- message (
aiobungie.UndefinedOr[str]): An optional message to send with the request. Default isUNDEFINED.
1462 async def add_optional_conversation( 1463 self, 1464 access_token: str, 1465 /, 1466 group_id: int, 1467 *, 1468 name: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1469 security: typing.Literal[0, 1] = 0, 1470 ) -> None: 1471 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1472 payload = {"chatName": str(name), "chatSecurity": security} 1473 await self._request( 1474 RequestMethod.POST, 1475 f"GroupV2/{group_id}/OptionalConversations/Add", 1476 json=payload, 1477 auth=access_token, 1478 )
Add a new chat channel to a group.
This request requires OAuth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The given group id.
Other parameters
name: aiobungie.UndefinedOr[str]
The chat name. Default to UNDEFINED
security: typing.Literal[0, 1]
The security level of the chat.
If provided and set to 0, It will be to `Group` only.
If provided and set to 1, It will be `Admins` only.
Default is `0`
1480 async def edit_optional_conversation( 1481 self, 1482 access_token: str, 1483 /, 1484 group_id: int, 1485 conversation_id: int, 1486 *, 1487 name: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1488 security: typing.Literal[0, 1] = 0, 1489 enable_chat: bool = False, 1490 ) -> None: 1491 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1492 payload = { 1493 "chatEnabled": enable_chat, 1494 "chatName": str(name), 1495 "chatSecurity": security, 1496 } 1497 await self._request( 1498 RequestMethod.POST, 1499 f"GroupV2/{group_id}/OptionalConversations/Edit/{conversation_id}", 1500 json=payload, 1501 auth=access_token, 1502 )
Edit the settings of this chat channel.
This request requires OAuth2: AdminGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The given group id. - conversation_id (
int): The conversation/chat id.
Other parameters
name: aiobungie.UndefinedOr[str]
The new chat name. Default to UNDEFINED
security: typing.Literal[0, 1]
The new security level of the chat.
If provided and set to 0, It will be to `Group` only.
If provided and set to 1, It will be `Admins` only.
Default is `0`
enable_chat : bool
Whether to enable chatting or not.
If set to True then chatting will be enabled. Otherwise it will be disabled.
1504 async def transfer_item( 1505 self, 1506 access_token: str, 1507 /, 1508 item_id: int, 1509 item_hash: int, 1510 character_id: int, 1511 member_type: typedefs.IntAnd[enums.MembershipType], 1512 *, 1513 stack_size: int = 1, 1514 vault: bool = False, 1515 ) -> None: 1516 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1517 payload = { 1518 "characterId": character_id, 1519 "membershipType": int(member_type), 1520 "itemId": item_id, 1521 "itemReferenceHash": item_hash, 1522 "stackSize": stack_size, 1523 "transferToVault": vault, 1524 } 1525 await self._request( 1526 RequestMethod.POST, 1527 "Destiny2/Actions/Items/TransferItem", 1528 json=payload, 1529 auth=access_token, 1530 )
Transfer an item from / to your vault.
Notes
- This method requires OAuth2: MoveEquipDestinyItems scope.
- This method requires both item id and hash.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - item_id (
int): The item instance id you to transfer. - item_hash (
int): The item hash. - character_id (
int): The character id to transfer the item from/to. - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The user membership type.
Other Parameters
- stack_size (
int): The item stack size. - valut (
bool): Whether to transfer this item to your valut or not. Defaults toFalse.
1532 async def pull_item( 1533 self, 1534 access_token: str, 1535 /, 1536 item_id: int, 1537 item_hash: int, 1538 character_id: int, 1539 member_type: typedefs.IntAnd[enums.MembershipType], 1540 *, 1541 stack_size: int = 1, 1542 vault: bool = False, 1543 ) -> None: 1544 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>> 1545 payload = { 1546 "characterId": character_id, 1547 "membershipType": int(member_type), 1548 "itemId": item_id, 1549 "itemReferenceHash": item_hash, 1550 "stackSize": stack_size, 1551 "transferToVault": vault, 1552 } 1553 await self._request( 1554 RequestMethod.POST, 1555 "Destiny2/Actions/Items/PullFromPostmaster", 1556 json=payload, 1557 auth=access_token, 1558 )
pull an item from the postmaster.
Notes
- This method requires OAuth2: MoveEquipDestinyItems scope.
- This method requires both item id and hash.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - item_id (
int): The item instance id to pull. - item_hash (
int): The item hash. - character_id (
int): The character id to pull the item to. - member_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The user membership type.
Other Parameters
- stack_size (
int): The item stack size. - valut (
bool): Whether to pill this item to your valut or not. Defaults toFalse.
1560 async def fetch_fireteams( 1561 self, 1562 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1563 *, 1564 platform: typedefs.IntAnd[ 1565 fireteams.FireteamPlatform 1566 ] = fireteams.FireteamPlatform.ANY, 1567 language: typing.Union[ 1568 fireteams.FireteamLanguage, str 1569 ] = fireteams.FireteamLanguage.ALL, 1570 date_range: typedefs.IntAnd[ 1571 fireteams.FireteamDate 1572 ] = fireteams.FireteamDate.ALL, 1573 page: int = 0, 1574 slots_filter: int = 0, 1575 ) -> typedefs.JSONObject: 1576 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1577 resp = await self._request( 1578 RequestMethod.GET, 1579 f"Fireteam/Search/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{page}/?langFilter={str(language)}", # noqa: E501 Line too long 1580 ) 1581 assert isinstance(resp, dict) 1582 return resp
Fetch public Bungie fireteams with open slots.
Parameters
- activity_type (
aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): The fireteam activity type.
Other Parameters
- platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - date_range (
aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): An integer to filter the date range of the returned fireteams. Defaults toaiobungie.FireteamDate.ALL. - page (
int): The page number. By default its0which returns all available activities. - slots_filter (
int): Filter the returned fireteams based on available slots. Default is0
Returns
aiobungie.typedefs.JSONObject: A JSON object of the fireteam details.
1584 async def fetch_avaliable_clan_fireteams( 1585 self, 1586 access_token: str, 1587 group_id: int, 1588 activity_type: typedefs.IntAnd[fireteams.FireteamActivity], 1589 *, 1590 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1591 language: typing.Union[fireteams.FireteamLanguage, str], 1592 date_range: typedefs.IntAnd[ 1593 fireteams.FireteamDate 1594 ] = fireteams.FireteamDate.ALL, 1595 page: int = 0, 1596 public_only: bool = False, 1597 slots_filter: int = 0, 1598 ) -> typedefs.JSONObject: 1599 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1600 resp = await self._request( 1601 RequestMethod.GET, 1602 f"Fireteam/Clan/{group_id}/Available/{int(platform)}/{int(activity_type)}/{int(date_range)}/{slots_filter}/{public_only}/{page}", # noqa: E501 1603 json={"langFilter": str(language)}, 1604 auth=access_token, 1605 ) 1606 assert isinstance(resp, dict) 1607 return resp
Fetch a clan's fireteams with open slots.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id of the fireteam. - activity_type (
aiobungie.typedefs.IntAnd[aiobungie.crates.FireteamActivity]): The fireteam activity type.
Other Parameters
- platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - date_range (
aiobungie.typedefs.IntAnd[aiobungie.FireteamDate]): An integer to filter the date range of the returned fireteams. Defaults toaiobungie.FireteamDate.ALL. - page (
int): The page number. By default its0which returns all available activities. - public_only (
bool): If set to True, Then only public fireteams will be returned. - slots_filter (
int): Filter the returned fireteams based on available slots. Default is0
Returns
aiobungie.typedefs.JSONObject: A JSON object of the fireteams detail.
1609 async def fetch_clan_fireteam( 1610 self, access_token: str, fireteam_id: int, group_id: int 1611 ) -> typedefs.JSONObject: 1612 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1613 resp = await self._request( 1614 RequestMethod.GET, 1615 f"Fireteam/Clan/{group_id}/Summary/{fireteam_id}", 1616 auth=access_token, 1617 ) 1618 assert isinstance(resp, dict) 1619 return resp
Fetch a specific clan fireteam.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id to fetch the fireteam from. - fireteam_id (
int): The fireteam id to fetch.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the fireteam details.
1621 async def fetch_my_clan_fireteams( 1622 self, 1623 access_token: str, 1624 group_id: int, 1625 *, 1626 include_closed: bool = True, 1627 platform: typedefs.IntAnd[fireteams.FireteamPlatform], 1628 language: typing.Union[fireteams.FireteamLanguage, str], 1629 filtered: bool = True, 1630 page: int = 0, 1631 ) -> typedefs.JSONObject: 1632 payload = {"groupFilter": filtered, "langFilter": str(language)} 1633 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1634 resp = await self._request( 1635 RequestMethod.GET, 1636 f"Fireteam/Clan/{group_id}/My/{int(platform)}/{include_closed}/{page}", 1637 json=payload, 1638 auth=access_token, 1639 ) 1640 assert isinstance(resp, dict) 1641 return resp
Fetch a clan's fireteams with open slots.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id to fetch.
Other Parameters
- include_closed (
bool): If provided and set toTrue, It will also return closed fireteams. If provided and set toFalse, It will only return public fireteams. Default isTrue. - platform (
aiobungie.typedefs.IntAnd[FireteamPlatform]): If this is provided. Then the results will be filtered with the given platform. Defaults toaiobungie.crates.FireteamPlatform.ANYwhich returns all platforms. - language (
typing.Union[FireteamLanguage, str]): A locale language to filter the used language in that fireteam. Defaults toaiobungie.crates.FireteamLanguage.ALL - filtered (
bool): If set toTrue, it will filter by clan. Otherwise not. Default isTrue. - page (
int): The page number. By default its0which returns all available activities.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the fireteams detail.
1643 async def fetch_private_clan_fireteams( 1644 self, access_token: str, group_id: int, / 1645 ) -> int: 1646 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1647 resp = await self._request( 1648 RequestMethod.GET, 1649 f"Fireteam/Clan/{group_id}/ActiveCount", 1650 auth=access_token, 1651 ) 1652 assert isinstance(resp, int) 1653 return resp
Fetch the active count of the clan fireteams that are only private.
This method requires OAuth2: ReadGroups scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - group_id (
int): The group/clan id.
Returns
int: The active fireteams count. Max value returned is 25.
1655 async def fetch_post_activity(self, instance_id: int, /) -> typedefs.JSONObject: 1656 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1657 resp = await self._request( 1658 RequestMethod.GET, f"Destiny2/Stats/PostGameCarnageReport/{instance_id}" 1659 ) 1660 assert isinstance(resp, dict) 1661 return resp
Fetch a post activity details.
Parameters
- instance_id (
int): The activity instance id.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the post activity.
1663 async def search_entities( 1664 self, name: str, entity_type: str, *, page: int = 0 1665 ) -> typedefs.JSONObject: 1666 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1667 resp = await self._request( 1668 RequestMethod.GET, 1669 f"Destiny2/Armory/Search/{entity_type}/{name}/", 1670 json={"page": page}, 1671 ) 1672 assert isinstance(resp, dict) 1673 return resp
Search for Destiny2 entities given a name and its type.
Parameters
- name (
str): The name of the entity, i.e., Thunderlord, One thousand voices. - entity_type (
str): The type of the entity, AKA Definition, For an exampleDestinyInventoryItemDefinition
Other Parameters
- page (
int): An optional page to return. Default to 0.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains details about the searched term.
1675 async def fetch_unique_weapon_history( 1676 self, 1677 membership_id: int, 1678 character_id: int, 1679 membership_type: typedefs.IntAnd[enums.MembershipType], 1680 ) -> typedefs.JSONObject: 1681 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1682 resp = await self._request( 1683 RequestMethod.GET, 1684 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/UniqueWeapons/", 1685 ) 1686 assert isinstance(resp, dict) 1687 return resp
Fetch details about unique weapon usage for a character. Includes all exotics.
Parameters
- membership_id (
int): The Destiny user membership id. - character_id (
int): The character id to retrieve. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny user's membership type.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains details about the returned weapons.
1689 async def fetch_item( 1690 self, 1691 member_id: int, 1692 item_id: int, 1693 membership_type: typedefs.IntAnd[enums.MembershipType], 1694 components: list[enums.ComponentType], 1695 ) -> typedefs.JSONObject: 1696 collector = _collect_components(components) 1697 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1698 resp = await self._request( 1699 RequestMethod.GET, 1700 f"Destiny2/{int(membership_type)}/Profile/{member_id}/Item/{item_id}/?components={collector}", 1701 ) 1702 assert isinstance(resp, dict) 1703 return resp
Fetch an instanced Destiny 2 item's details.
Parameters
- member_id (
int): The membership id of the Destiny 2 player. - item_id (
int): The instance id of the item. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The membership type of the Destiny 2 player. - components (
list[aiobungie.ComponentType]): A list of components to retrieve.
Returns
aiobungie.typedefs.JSONObject: A JSON object response contains the fetched item with its components.
1705 async def fetch_clan_weekly_rewards(self, clan_id: int, /) -> typedefs.JSONObject: 1706 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1707 resp = await self._request( 1708 RequestMethod.GET, f"Destiny2/Clan/{clan_id}/WeeklyRewardState/" 1709 ) 1710 assert isinstance(resp, dict) 1711 return resp
Fetch the weekly reward state for a clan.
Parameters
- clan_id (
int): The clan id.
Returns
aiobungie.typedefs.JSONObject: A JSON response of the clan rewards state.
1713 async def fetch_available_locales(self) -> typedefs.JSONObject: 1714 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1715 resp = await self._request( 1716 RequestMethod.GET, "Destiny2/Manifest/DestinyLocaleDefinition/" 1717 ) 1718 assert isinstance(resp, dict) 1719 return resp
Fetch available locales at Bungie.
Returns
aiobungie.typedefs.JSONObject: A JSON object contains a list of all available localization cultures.
1721 async def fetch_common_settings(self) -> typedefs.JSONObject: 1722 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1723 resp = await self._request(RequestMethod.GET, "Settings") 1724 assert isinstance(resp, dict) 1725 return resp
Fetch the common settings used by Bungie's envirotment.
Returns
aiobungie.typedefs.JSONObject: The common settings JSON object.
1727 async def fetch_user_systems_overrides(self) -> typedefs.JSONObject: 1728 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1729 resp = await self._request(RequestMethod.GET, "UserSystemOverrides") 1730 assert isinstance(resp, dict) 1731 return resp
Fetch a user's specific system overrides.
Returns
aiobungie.typedefs.JSONObject: The system overrides JSON object.
1733 async def fetch_global_alerts( 1734 self, *, include_streaming: bool = False 1735 ) -> typedefs.JSONArray: 1736 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1737 resp = await self._request( 1738 RequestMethod.GET, f"GlobalAlerts/?includestreaming={include_streaming}" 1739 ) 1740 assert isinstance(resp, list) 1741 return resp
Fetch any active global alerts.
Parameters
- include_streaming (
bool): If True, the returned results will include streaming alerts. Default is False.
Returns
aiobungie.typedefs.JSONArray: A JSON array of the global alerts objects.
1743 async def awainitialize_request( 1744 self, 1745 access_token: str, 1746 type: typing.Literal[0, 1], 1747 membership_type: typedefs.IntAnd[enums.MembershipType], 1748 /, 1749 *, 1750 affected_item_id: typing.Optional[int] = None, 1751 character_id: typing.Optional[int] = None, 1752 ) -> typedefs.JSONObject: 1753 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1754 1755 body = {"type": type, "membershipType": int(membership_type)} 1756 1757 if affected_item_id is not None: 1758 body["affectedItemId"] = affected_item_id 1759 1760 if character_id is not None: 1761 body["characterId"] = character_id 1762 1763 resp = await self._request( 1764 RequestMethod.POST, "Destiny2/Awa/Initialize", json=body, auth=access_token 1765 ) 1766 assert isinstance(resp, dict) 1767 return resp
Initialize a request to perform an advanced write action.
OAuth2: AdvancedWriteActions application scope is required to perform this request.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - type (
typing.Literal[0, 1]): Type of the advanced write action. Its either 0 or 1. If set to 0 that means itNone. Otherwise if 1 that means its insert plugs. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny membership type of the account to modify.
Other Parameters
- affected_item_id (
typing.Optional[int]): Item instance ID the action shall be applied to. This is optional for all but a new AwaType values. - character_id (
typing.Optional[int]): The Destiny character ID to perform this action on.
Returns
aiobungie.typedefs.JSONObject: A JSON object response.
1769 async def awaget_action_token( 1770 self, access_token: str, correlation_id: str, / 1771 ) -> typedefs.JSONObject: 1772 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1773 resp = await self._request( 1774 RequestMethod.POST, 1775 f"Destiny2/Awa/GetActionToken/{correlation_id}", 1776 auth=access_token, 1777 ) 1778 assert isinstance(resp, dict) 1779 return resp
Returns the action token if user approves the request.
OAuth2: AdvancedWriteActions application scope is required to perform this request.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - correlation_id (
str): The identifier for the advanced write action request.
Returns
aiobungie.typedefs.JSONObject: A JSON object response.
1801 async def fetch_vendors( 1802 self, 1803 access_token: str, 1804 character_id: int, 1805 membership_id: int, 1806 membership_type: typedefs.IntAnd[enums.MembershipType], 1807 /, 1808 components: list[enums.ComponentType], 1809 filter: typing.Optional[int] = None, 1810 ) -> typedefs.JSONObject: 1811 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1812 components_ = _collect_components(components) 1813 route = ( 1814 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" 1815 f"/Character/{character_id}/Vendors/?components={components_}" 1816 ) 1817 1818 if filter is not None: 1819 route = route + f"&filter={filter}" 1820 1821 resp = await self._request( 1822 RequestMethod.GET, 1823 route, 1824 auth=access_token, 1825 ) 1826 assert isinstance(resp, dict) 1827 return resp
Get currently available vendors from the list of vendors that can possibly have rotating inventory.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - character_id (
int): The character ID to return the vendor info for. - membership_id (
int): The Destiny membership id to return the vendor info for. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny membership type to return the vendor info for. - components (
list[aiobungie.ComponentType]): A list of vendor components to collect and return.
Other Parameters
- filter (
int): Filters the type of items returned from the vendor. This can be left toNone.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the vendor response.
1829 async def fetch_vendor( 1830 self, 1831 access_token: str, 1832 character_id: int, 1833 membership_id: int, 1834 membership_type: typedefs.IntAnd[enums.MembershipType], 1835 vendor_hash: int, 1836 /, 1837 components: list[enums.ComponentType], 1838 ) -> typedefs.JSONObject: 1839 # <<inherited docstring from aiobungie.interfaces.rest.RESTInterface>>. 1840 components_ = _collect_components(components) 1841 resp = await self._request( 1842 RequestMethod.GET, 1843 ( 1844 f"Destiny2/{int(membership_type)}/Profile/{membership_id}" 1845 f"/Character/{character_id}/Vendors/{vendor_hash}/?components={components_}" 1846 ), 1847 auth=access_token, 1848 ) 1849 assert isinstance(resp, dict) 1850 return resp
Fetch details for a specific vendor.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - character_id (
int): The character ID to return the vendor info for. - membership_id (
int): The Destiny membership id to return the vendor info for. - membership_type (
aiobungie.typedefs.IntAnd[aiobungie.MembershipType]): The Destiny membership type to return the vendor info for. - vendor_hash (
int): The vendor hash to return the details for. - components (
list[aiobungie.ComponentType]): A list of vendor components to collect and return.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the vendor response.
1852 async def fetch_application_api_usage( 1853 self, 1854 access_token: str, 1855 application_id: int, 1856 /, 1857 *, 1858 start: typing.Optional[datetime.datetime] = None, 1859 end: typing.Optional[datetime.datetime] = None, 1860 ) -> typedefs.JSONObject: 1861 end_date, start_date = time.parse_date_range(end, start) 1862 resp = await self._request( 1863 RequestMethod.GET, 1864 f"App/ApiUsage/{application_id}/?end={end_date}&start={start_date}", 1865 auth=access_token, 1866 ) 1867 assert isinstance(resp, dict) 1868 return resp
Fetch a Bungie application's API usage.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - application_id (
int): The application id to get.
Other Parameters
start (
typing.Optional[datetime.datetime]): A datetime object can be used to collect the start of the application usage. This is limited and can go back to 30 days maximum.If this is left to
None. It will return the last 24 hours.end (
typing.Optional[datetime.datetime]): A datetime object can be used to collect the end of the application usage.If this is left to
None. It will returnnow.
Example
import datetime
# Fetch data from 2021 Dec 10th to 2021 Dec 20th
await fetch_application_api_usage(
start=datetime.datetime(2021, 12, 10), end=datetime.datetime(2021, 12, 20)
)
Returns
aiobungie.typedefs.JSONObject: A JSON object of the application usage details.
1870 async def fetch_bungie_applications(self) -> typedefs.JSONArray: 1871 resp = await self._request(RequestMethod.GET, "App/FirstParty") 1872 assert isinstance(resp, list) 1873 return resp
Fetch details for applications created by Bungie.
Returns
aiobungie.typedefs.JSONArray: An array of Bungie created applications.
1880 async def fetch_content_by_id( 1881 self, id: int, locale: str, /, *, head: bool = False 1882 ) -> typedefs.JSONObject: 1883 resp = await self._request( 1884 RequestMethod.GET, 1885 f"Content/GetContentById/{id}/{locale}/", 1886 json={"head": head}, 1887 ) 1888 assert isinstance(resp, dict) 1889 return resp
1891 async def fetch_content_by_tag_and_type( 1892 self, locale: str, tag: str, type: str, *, head: bool = False 1893 ) -> typedefs.JSONObject: 1894 resp = await self._request( 1895 RequestMethod.GET, 1896 f"Content/GetContentByTagAndType/{tag}/{type}/{locale}/", 1897 json={"head": head}, 1898 ) 1899 assert isinstance(resp, dict) 1900 return resp
1902 async def search_content_with_text( 1903 self, 1904 locale: str, 1905 /, 1906 content_type: str, 1907 search_text: str, 1908 tag: str, 1909 *, 1910 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1911 source: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1912 ) -> typedefs.JSONObject: 1913 body: typedefs.JSONObject = {} 1914 1915 body["ctype"] = content_type 1916 body["searchtext"] = search_text 1917 body["tag"] = tag 1918 1919 if page is not undefined.UNDEFINED: 1920 body["currentpage"] = page 1921 else: 1922 body["currentpage"] = 1 1923 1924 if source is not undefined.UNDEFINED: 1925 body["source"] = source 1926 else: 1927 source = "" 1928 resp = await self._request( 1929 RequestMethod.GET, f"Content/Search/{locale}/", json=body 1930 ) 1931 assert isinstance(resp, dict) 1932 return resp
1934 async def search_content_by_tag_and_type( 1935 self, 1936 locale: str, 1937 tag: str, 1938 type: str, 1939 *, 1940 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1941 ) -> typedefs.JSONObject: 1942 body: typedefs.JSONObject = {} 1943 body["currentpage"] = 1 if page is undefined.UNDEFINED else page 1944 resp = await self._request( 1945 RequestMethod.GET, 1946 f"Content/SearchContentByTagAndType/{tag}/{type}/{locale}/", 1947 json=body, 1948 ) 1949 assert isinstance(resp, dict) 1950 return resp
1961 async def fetch_topics_page( 1962 self, 1963 category_filter: int, 1964 group: int, 1965 date_filter: int, 1966 sort: typing.Union[str, bytes], 1967 *, 1968 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 1969 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.UNDEFINED, 1970 tag_filter: undefined.UndefinedOr[str] = undefined.UNDEFINED, 1971 ) -> typedefs.JSONObject: 1972 body: typedefs.JSONObject = {} 1973 if locales is not undefined.UNDEFINED: 1974 body["locales"] = ",".join(str(locales)) 1975 else: 1976 body["locales"] = ",".join([]) 1977 1978 if tag_filter is not undefined.UNDEFINED: 1979 body["tagstring"] = tag_filter 1980 else: 1981 body["tagstring"] = "" 1982 1983 page = 0 if page is not undefined.UNDEFINED else page 1984 1985 resp = await self._request( 1986 RequestMethod.GET, 1987 f"Forum/GetTopicsPaged/{page}/{0}/{group}/{sort!s}/{date_filter}/{category_filter}/", 1988 json=body, 1989 ) 1990 assert isinstance(resp, dict) 1991 return resp
1993 async def fetch_core_topics_page( 1994 self, 1995 category_filter: int, 1996 date_filter: int, 1997 sort: typing.Union[str, bytes], 1998 *, 1999 page: undefined.UndefinedOr[int] = undefined.UNDEFINED, 2000 locales: undefined.UndefinedOr[collections.Iterable[str]] = undefined.UNDEFINED, 2001 ) -> typedefs.JSONObject: 2002 body: typedefs.JSONObject = {} 2003 2004 if locales is not undefined.UNDEFINED: 2005 body["locales"] = ",".join(str(locales)) 2006 else: 2007 body["locales"] = ",".join([]) 2008 2009 resp = await self._request( 2010 RequestMethod.GET, 2011 f"Forum/GetCoreTopicsPaged/{0 if page is undefined.UNDEFINED else page}" 2012 f"/{sort!s}/{date_filter}/{category_filter}/", 2013 json=body, 2014 ) 2015 assert isinstance(resp, dict) 2016 return resp
2018 async def fetch_posts_threaded_page( 2019 self, 2020 parent_post: bool, 2021 page: int, 2022 page_size: int, 2023 parent_post_id: int, 2024 reply_size: int, 2025 root_thread_mode: bool, 2026 sort_mode: int, 2027 show_banned: typing.Optional[str] = None, 2028 ) -> typedefs.JSONObject: 2029 resp = await self._request( 2030 RequestMethod.GET, 2031 f"Forum/GetPostsThreadedPaged/{parent_post}/{page}/" 2032 f"{page_size}/{reply_size}/{parent_post_id}/{root_thread_mode}/{sort_mode}/", 2033 json={"showbanned": show_banned}, 2034 ) 2035 assert isinstance(resp, dict) 2036 return resp
2038 async def fetch_posts_threaded_page_from_child( 2039 self, 2040 child_id: bool, 2041 page: int, 2042 page_size: int, 2043 reply_size: int, 2044 root_thread_mode: bool, 2045 sort_mode: int, 2046 show_banned: typing.Optional[str] = None, 2047 ) -> typedefs.JSONObject: 2048 resp = await self._request( 2049 RequestMethod.GET, 2050 f"Forum/GetPostsThreadedPagedFromChild/{child_id}/" 2051 f"{page}/{page_size}/{reply_size}/{root_thread_mode}/{sort_mode}/", 2052 json={"showbanned": show_banned}, 2053 ) 2054 assert isinstance(resp, dict) 2055 return resp
2057 async def fetch_post_and_parent( 2058 self, child_id: int, /, *, show_banned: typing.Optional[str] = None 2059 ) -> typedefs.JSONObject: 2060 resp = await self._request( 2061 RequestMethod.GET, 2062 f"Forum/GetPostAndParent/{child_id}/", 2063 json={"showbanned": show_banned}, 2064 ) 2065 assert isinstance(resp, dict) 2066 return resp
2068 async def fetch_posts_and_parent_awaiting( 2069 self, child_id: int, /, *, show_banned: typing.Optional[str] = None 2070 ) -> typedefs.JSONObject: 2071 resp = await self._request( 2072 RequestMethod.GET, 2073 f"Forum/GetPostAndParentAwaitingApproval/{child_id}/", 2074 json={"showbanned": show_banned}, 2075 ) 2076 assert isinstance(resp, dict) 2077 return resp
2107 async def fetch_recommended_groups( 2108 self, 2109 accecss_token: str, 2110 /, 2111 *, 2112 date_range: int = 0, 2113 group_type: typedefs.IntAnd[enums.GroupType] = enums.GroupType.CLAN, 2114 ) -> typedefs.JSONArray: 2115 resp = await self._request( 2116 RequestMethod.POST, 2117 f"GroupV2/Recommended/{int(group_type)}/{date_range}/", 2118 auth=accecss_token, 2119 ) 2120 assert isinstance(resp, list) 2121 return resp
2128 async def fetch_user_clan_invite_setting( 2129 self, 2130 access_token: str, 2131 /, 2132 membership_type: typedefs.IntAnd[enums.MembershipType], 2133 ) -> bool: 2134 resp = await self._request( 2135 RequestMethod.GET, 2136 f"GroupV2/GetUserClanInviteSetting/{int(membership_type)}/", 2137 auth=access_token, 2138 ) 2139 assert isinstance(resp, bool) 2140 return resp
2142 async def fetch_banned_group_members( 2143 self, access_token: str, group_id: int, /, *, page: int = 1 2144 ) -> typedefs.JSONObject: 2145 resp = await self._request( 2146 RequestMethod.GET, 2147 f"GroupV2/{group_id}/Banned/?currentpage={page}", 2148 auth=access_token, 2149 ) 2150 assert isinstance(resp, dict) 2151 return resp
2153 async def fetch_pending_group_memberships( 2154 self, access_token: str, group_id: int, /, *, current_page: int = 1 2155 ) -> typedefs.JSONObject: 2156 resp = await self._request( 2157 RequestMethod.GET, 2158 f"GroupV2/{group_id}/Members/Pending/?currentpage={current_page}", 2159 auth=access_token, 2160 ) 2161 assert isinstance(resp, dict) 2162 return resp
2164 async def fetch_invited_group_memberships( 2165 self, access_token: str, group_id: int, /, *, current_page: int = 1 2166 ) -> typedefs.JSONObject: 2167 resp = await self._request( 2168 RequestMethod.GET, 2169 f"GroupV2/{group_id}/Members/InvitedIndividuals/?currentpage={current_page}", 2170 auth=access_token, 2171 ) 2172 assert isinstance(resp, dict) 2173 return resp
2175 async def invite_member_to_group( 2176 self, 2177 access_token: str, 2178 /, 2179 group_id: int, 2180 membership_id: int, 2181 membership_type: typedefs.IntAnd[enums.MembershipType], 2182 *, 2183 message: undefined.UndefinedOr[str] = undefined.UNDEFINED, 2184 ) -> typedefs.JSONObject: 2185 resp = await self._request( 2186 RequestMethod.POST, 2187 f"GroupV2/{group_id}/Members/IndividualInvite/{int(membership_type)}/{membership_id}/", 2188 auth=access_token, 2189 json={"message": str(message)}, 2190 ) 2191 assert isinstance(resp, dict) 2192 return resp
2194 async def cancel_group_member_invite( 2195 self, 2196 access_token: str, 2197 /, 2198 group_id: int, 2199 membership_id: int, 2200 membership_type: typedefs.IntAnd[enums.MembershipType], 2201 ) -> typedefs.JSONObject: 2202 resp = await self._request( 2203 RequestMethod.POST, 2204 f"GroupV2/{group_id}/Members/IndividualInviteCancel/{int(membership_type)}/{membership_id}/", 2205 auth=access_token, 2206 ) 2207 assert isinstance(resp, dict) 2208 return resp
2215 async def fetch_historical_stats( 2216 self, 2217 character_id: int, 2218 membership_id: int, 2219 membership_type: typedefs.IntAnd[enums.MembershipType], 2220 day_start: datetime.datetime, 2221 day_end: datetime.datetime, 2222 groups: list[typedefs.IntAnd[enums.StatsGroupType]], 2223 modes: collections.Sequence[typedefs.IntAnd[enums.GameMode]], 2224 *, 2225 period_type: enums.PeriodType = enums.PeriodType.ALL_TIME, 2226 ) -> typedefs.JSONObject: 2227 end, start = time.parse_date_range(day_end, day_start) 2228 resp = await self._request( 2229 RequestMethod.GET, 2230 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Character/{character_id}/Stats/", 2231 json={ 2232 "dayend": end, 2233 "daystart": start, 2234 "groups": [str(int(group)) for group in groups], 2235 "modes": [str(int(mode)) for mode in modes], 2236 "periodType": int(period_type), 2237 }, 2238 ) 2239 assert isinstance(resp, dict) 2240 return resp
Fetch historical stats for a specific membership character.
Parameters
- character_id (
int): The character ID to return the stats for. - membership_id (
int): The Destiny membership id to return the stats for. - membership_type (
aiobungie.MembershipType | int): The Destiny membership type to return the stats for. - day_start (
datetime.datetime): The start of the day to return the stats for. - day_end (
datetime.datetime): The end of the day to return the stats for. - groups (
list[aiobungie.StatsGroupType]): A list of stats groups to return. - modes (
list[aiobungie.GameMode | int]): A list of game modes to return. - period_type (
aiobungie.enums.PeriodType): The period type to return the stats for. This will returnALL_TIMEby default if not modified.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the historical stats.
2242 async def fetch_historical_stats_for_account( 2243 self, 2244 membership_id: int, 2245 membership_type: typedefs.IntAnd[enums.MembershipType], 2246 groups: list[typedefs.IntAnd[enums.StatsGroupType]], 2247 ) -> typedefs.JSONObject: 2248 resp = await self._request( 2249 RequestMethod.GET, 2250 f"Destiny2/{int(membership_type)}/Account/{membership_id}/Stats/", 2251 json={"groups": [str(int(group)) for group in groups]}, 2252 ) 2253 assert isinstance(resp, dict) 2254 return resp
Fetch historical stats for an account's membership.
Parameters
- membership_id (
int): The Destiny membership id to return the stats for. - membership_type (
aiobungie.MembershipType | int): The Destiny membership type to return the stats for. - groups (
list[aiobungie.StatsGroupType]): A list of stats groups to return.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the historical stats for the account. This includes both the character and account stats.
2256 async def fetch_aggregated_activity_stats( 2257 self, 2258 character_id: int, 2259 membership_id: int, 2260 membership_type: typedefs.IntAnd[enums.MembershipType], 2261 /, 2262 ) -> typedefs.JSONObject: 2263 resp = await self._request( 2264 RequestMethod.GET, 2265 f"Destiny2/{int(membership_type)}/Account/{membership_id}/" 2266 f"Character/{character_id}/Stats/AggregateActivityStats/", 2267 ) 2268 assert isinstance(resp, dict) 2269 return resp
Fetch aggregated activity stats for a specific membership character.
Parameters
- character_id (
int): The character ID to return the stats for. - membership_id (
int): The Destiny membership id to return the stats for. - membership_type (
aiobungie.MembershipType | int): The Destiny membership type to return the stats for.
Returns
aiobungie.typedefs.JSONObject: A JSON object of the aggregated activity stats.
2271 async def equip_loadout( 2272 self, 2273 access_token: str, 2274 /, 2275 loadout_index: int, 2276 character_id: int, 2277 membership_type: typedefs.IntAnd[enums.MembershipType], 2278 ) -> None: 2279 response = await self._request( 2280 RequestMethod.POST, 2281 "Destiny2/Actions/Loadouts/EquipLoadout/", 2282 json={ 2283 "loadoutIndex": loadout_index, 2284 "characterId": character_id, 2285 "membership_type": int(membership_type), 2286 }, 2287 auth=access_token, 2288 ) 2289 assert isinstance(response, int)
Equip a loadout. Youe character must be in a Social space, Orbit or Offline while performing this operation.
This operation requires MoveEquipDestinyItems OAuth2 scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - loadout_index (
int): The index of the loadout to use. - character_id (
int): The character ID to equip the loadout to. - membership_type (
aiobungie.MembershipType | int): The membership type of the account.
2291 async def snapshot_loadout( 2292 self, 2293 access_token: str, 2294 /, 2295 loadout_index: int, 2296 character_id: int, 2297 membership_type: typedefs.IntAnd[enums.MembershipType], 2298 *, 2299 color_hash: typing.Optional[int] = None, 2300 icon_hash: typing.Optional[int] = None, 2301 name_hash: typing.Optional[int] = None, 2302 ) -> None: 2303 response = await self._request( 2304 RequestMethod.POST, 2305 "Destiny2/Actions/Loadouts/SnapshotLoadout/", 2306 auth=access_token, 2307 json={ 2308 "colorHash": color_hash, 2309 "iconHash": icon_hash, 2310 "nameHash": name_hash, 2311 "loadoutIndex": loadout_index, 2312 "characterId": character_id, 2313 "membershipType": int(membership_type), 2314 }, 2315 ) 2316 assert isinstance(response, int)
Snapshot a loadout with the currently equipped items.
This operation requires MoveEquipDestinyItems OAuth2 scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - loadout_index (
int): The index of the loadout to use. - character_id (
int): The character ID to equip the loadout to. - membership_type (
aiobungie.MembershipType | int): The membership type of the account.
Other Parameters
- color_hash (
int | None): ... - icon_hash (
int | None): ... - name_hash (
int | None): ...
2318 async def update_loadout( 2319 self, 2320 access_token: str, 2321 /, 2322 loadout_index: int, 2323 character_id: int, 2324 membership_type: typedefs.IntAnd[enums.MembershipType], 2325 *, 2326 color_hash: typing.Optional[int] = None, 2327 icon_hash: typing.Optional[int] = None, 2328 name_hash: typing.Optional[int] = None, 2329 ) -> None: 2330 response = await self._request( 2331 RequestMethod.POST, 2332 "Destiny2/Actions/Loadouts/UpdateLoadoutIdentifiers/", 2333 auth=access_token, 2334 json={ 2335 "colorHash": color_hash, 2336 "iconHash": icon_hash, 2337 "nameHash": name_hash, 2338 "loadoutIndex": loadout_index, 2339 "characterId": character_id, 2340 "membershipType": int(membership_type), 2341 }, 2342 ) 2343 assert isinstance(response, int)
Update the loadout. Color, Icon and Name.
This operation requires MoveEquipDestinyItems OAuth2 scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - loadout_index (
int): The index of the loadout to use. - character_id (
int): The character ID to equip the loadout to. - membership_type (
aiobungie.MembershipType | int): The membership type of the account.
Other Parameters
- color_hash (
int | None): The new color hash of the loadout to update. - icon_hash (
int | None): The new icon hash of the loadout to update. - name_hash (
int | None): The new name hash of the loadout to update.
2345 async def clear_loadout( 2346 self, 2347 access_token: str, 2348 /, 2349 loadout_index: int, 2350 character_id: int, 2351 membership_type: typedefs.IntAnd[enums.MembershipType], 2352 ) -> None: 2353 response = await self._request( 2354 RequestMethod.POST, 2355 "Destiny2/Actions/Loadouts/ClearLoadout/", 2356 json={ 2357 "loadoutIndex": loadout_index, 2358 "characterId": character_id, 2359 "membership_type": int(membership_type), 2360 }, 2361 auth=access_token, 2362 ) 2363 assert isinstance(response, int)
Clear the identifiers and items of a loadout.
This operation requires MoveEquipDestinyItems OAuth2 scope.
Parameters
- access_token (
str): The bearer access token associated with the bungie account. - loadout_index (
int): The index of the loadout to use. - character_id (
int): The character ID to equip the loadout to. - membership_type (
aiobungie.MembershipType | int): The membership type of the account.
196class RESTPool: 197 """Pool of `RESTClient` instances. 198 199 This allows to create multiple instances of `RESTClient`s that can be acquired 200 which share the same config and metadata. 201 202 Example 203 ------- 204 ```py 205 import aiobungie 206 import asyncio 207 208 client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret') 209 210 # Using a context manager to acquire an instance 211 # of the pool and close the connection after finishing. 212 213 async def first() -> str: 214 async with client_pool.acquire() as client: 215 return client.build_oauth2_url() 216 217 async def second() -> None: 218 async with client_pool.acquire() as client: 219 new_tokens = await client.refresh_access_token("token") 220 client.metadata['tokens'] = new_tokens 221 222 # Client instances are independent from first and second. 223 await asyncio.gather(first(), second()) 224 ``` 225 226 Parameters 227 ---------- 228 token : `str` 229 A valid application token from Bungie's developer portal. 230 231 Other Parameters 232 ---------------- 233 max_retries : `int` 234 The max retries number to retry if the request hit a `5xx` status code. 235 client_secret : `typing.Optional[str]` 236 An optional application client secret, 237 This is only needed if you're fetching OAuth2 tokens with this client. 238 client_id : `typing.Optional[int]` 239 An optional application client id, 240 This is only needed if you're fetching OAuth2 tokens with this client. 241 enable_debugging : `bool | str` 242 Whether to enable logging responses or not. 243 244 Logging Levels 245 -------------- 246 * `False`: This will disable logging. 247 * `True`: This will set the level to `DEBUG` and enable logging minimal information. 248 Like the response status, route, taken time and so on. 249 * `"TRACE" | aiobungie.TRACE`: This will log the response headers along with the minimal information. 250 """ 251 252 __slots__ = ( 253 "_token", 254 "_max_retries", 255 "_client_secret", 256 "_client_id", 257 "_metadata", 258 "_enable_debug", 259 "_client_session", 260 ) 261 262 # Looks like mypy doesn't like this. 263 if typing.TYPE_CHECKING: 264 _enable_debug: typing.Union[typing.Literal["TRACE"], bool, int] 265 266 def __init__( 267 self, 268 token: str, 269 /, 270 *, 271 client_secret: typing.Optional[str] = None, 272 client_id: typing.Optional[int] = None, 273 client_session: typing.Optional[aiohttp.ClientSession] = None, 274 max_retries: int = 4, 275 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, 276 ) -> None: 277 self._client_secret = client_secret 278 self._client_id = client_id 279 self._token: str = token 280 self._max_retries = max_retries 281 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} 282 self._enable_debug = enable_debugging 283 self._client_session = client_session 284 285 @property 286 def client_id(self) -> typing.Optional[int]: 287 return self._client_id 288 289 @property 290 def metadata(self) -> collections.MutableMapping[typing.Any, typing.Any]: 291 """Pool's Metadata. This is different from client instance metadata.""" 292 return self._metadata 293 294 @typing.final 295 def acquire(self) -> RESTClient: 296 """Acquires a new `RESTClient` instance from this REST pool. 297 298 Returns 299 ------- 300 `RESTClient` 301 An instance of a REST client. 302 """ 303 return RESTClient( 304 self._token, 305 client_secret=self._client_secret, 306 client_id=self._client_id, 307 max_retries=self._max_retries, 308 enable_debugging=self._enable_debug, 309 client_session=self._client_session, 310 )
Pool of RESTClient instances.
This allows to create multiple instances of RESTClients that can be acquired
which share the same config and metadata.
Example
import aiobungie
import asyncio
client_pool = aiobungie.RESTPool("token", client_id=1234, client_secret='secret')
# Using a context manager to acquire an instance
# of the pool and close the connection after finishing.
async def first() -> str:
async with client_pool.acquire() as client:
return client.build_oauth2_url()
async def second() -> None:
async with client_pool.acquire() as client:
new_tokens = await client.refresh_access_token("token")
client.metadata['tokens'] = new_tokens
# Client instances are independent from first and second.
await asyncio.gather(first(), second())
Parameters
- token (
str): A valid application token from Bungie's developer portal.
Other Parameters
- max_retries (
int): The max retries number to retry if the request hit a5xxstatus code. - client_secret (
typing.Optional[str]): An optional application client secret, This is only needed if you're fetching OAuth2 tokens with this client. - client_id (
typing.Optional[int]): An optional application client id, This is only needed if you're fetching OAuth2 tokens with this client. - enable_debugging (
bool | str): Whether to enable logging responses or not.
Logging Levels
False: This will disable logging.True: This will set the level toDEBUGand enable logging minimal information. Like the response status, route, taken time and so on."TRACE" | TRACE: This will log the response headers along with the minimal information.
266 def __init__( 267 self, 268 token: str, 269 /, 270 *, 271 client_secret: typing.Optional[str] = None, 272 client_id: typing.Optional[int] = None, 273 client_session: typing.Optional[aiohttp.ClientSession] = None, 274 max_retries: int = 4, 275 enable_debugging: typing.Union[typing.Literal["TRACE"], bool, int] = False, 276 ) -> None: 277 self._client_secret = client_secret 278 self._client_id = client_id 279 self._token: str = token 280 self._max_retries = max_retries 281 self._metadata: collections.MutableMapping[typing.Any, typing.Any] = {} 282 self._enable_debug = enable_debugging 283 self._client_session = client_session
Pool's Metadata. This is different from client instance metadata.
294 @typing.final 295 def acquire(self) -> RESTClient: 296 """Acquires a new `RESTClient` instance from this REST pool. 297 298 Returns 299 ------- 300 `RESTClient` 301 An instance of a REST client. 302 """ 303 return RESTClient( 304 self._token, 305 client_secret=self._client_secret, 306 client_id=self._client_id, 307 max_retries=self._max_retries, 308 enable_debugging=self._enable_debug, 309 client_session=self._client_session, 310 )
Acquires a new RESTClient instance from this REST pool.
Returns
RESTClient: An instance of a REST client.
495@typing.final 496class Race(int, Enum): 497 """An Enum for Destiny races.""" 498 499 HUMAN = 0 500 AWOKEN = 1 501 EXO = 2 502 UNKNOWN = 3
An Enum for Destiny races.
143@typing.final 144class Raid(int, Enum): 145 """An Enum for all available raids in Destiny 2.""" 146 147 DSC = 910380154 148 """Deep Stone Crypt""" 149 150 LW = 2122313384 151 """Last Wish""" 152 153 VOG = 3881495763 154 """Normal Valut of Glass""" 155 156 GOS = 3458480158 157 """Garden Of Salvation"""
An Enum for all available raids in Destiny 2.
253@attrs.define(auto_exc=True) 254class RateLimitedError(HTTPError): 255 """Raised when too many request status code is returned.""" 256 257 http_status: http.HTTPStatus = attrs.field( 258 default=http.HTTPStatus.TOO_MANY_REQUESTS, init=False 259 ) 260 """The request response http status.""" 261 262 url: typedefs.StrOrURL 263 """The URL/endpoint caused this error.""" 264 265 body: typing.Any 266 """The response body.""" 267 268 retry_after: float = attrs.field(default=0.0) 269 """The amount of seconds you need to wait before retrying to requests.""" 270 271 message: str = attrs.field(init=False) 272 """A Bungie human readable message describes the cause of the error.""" 273 274 @message.default # type: ignore 275 def _(self) -> str: 276 return f"You're ratelimited for {self.retry_after}, Endpoint: {self.url}. Slow down!" 277 278 def __str__(self) -> str: 279 return self.message
Raised when too many request status code is returned.
2def __init__(self, url, body, retry_after=attr_dict['retry_after'].default): 3 self.http_status = attr_dict['http_status'].default 4 self.url = url 5 self.body = body 6 self.retry_after = retry_after 7 self.message = __attr_factory_message(self) 8 BaseException.__init__(self, self.url,self.body,self.retry_after)
Method generated by attrs for class RateLimitedError.
Inherited Members
- builtins.BaseException
- with_traceback
- args
48@typing.final 49class RecordState(enums.Flag): 50 """An enum for records component states.""" 51 52 NONE = 0 53 REDEEMED = 1 << 0 54 UNAVAILABLE = 1 << 1 55 OBJECTIVE_NOT_COMPLETED = 1 << 2 56 OBSCURED = 1 << 3 57 INVISIBLE = 1 << 4 58 ENTITLEMENT_UNOWNED = 1 << 5 59 CAN_EQUIP_TITLE = 1 << 6
An enum for records component states.
690@typing.final 691class Relationship(int, Enum): 692 """An enum for bungie friends relationship types.""" 693 694 UNKNOWN = 0 695 FRIEND = 1 696 INCOMING_REQUEST = 2 697 OUTGOING_REQUEST = 3
An enum for bungie friends relationship types.
181class RequestMethod(str, enums.Enum): 182 """HTTP request methods enum.""" 183 184 GET = "GET" 185 """GET methods.""" 186 POST = "POST" 187 """POST methods.""" 188 PUT = "PUT" 189 """PUT methods.""" 190 PATCH = "PATCH" 191 """PATCH methods.""" 192 DELETE = "DELETE" 193 """DELETE methods"""
HTTP request methods enum.
Inherited Members
- builtins.str
- encode
- replace
- split
- rsplit
- join
- capitalize
- casefold
- title
- center
- count
- expandtabs
- find
- partition
- index
- ljust
- lower
- lstrip
- rfind
- rindex
- rjust
- rstrip
- rpartition
- splitlines
- strip
- swapcase
- translate
- upper
- startswith
- endswith
- removeprefix
- removesuffix
- isascii
- islower
- isupper
- istitle
- isspace
- isdecimal
- isdigit
- isnumeric
- isalpha
- isalnum
- isidentifier
- isprintable
- zfill
- format
- format_map
- maketrans
248@attrs.define(auto_exc=True) 249class ResponseError(HTTPException): 250 """Exception for other HTTP response errors."""
Exception for other HTTP response errors.
2def __init__(self, *, error_code, http_status, throttle_seconds, url, body, headers, message, error_status, message_data): 3 self.error_code = error_code 4 self.http_status = http_status 5 self.throttle_seconds = throttle_seconds 6 self.url = url 7 self.body = body 8 self.headers = headers 9 self.message = message 10 self.error_status = error_status 11 self.message_data = message_data 12 BaseException.__init__(self, self.error_code,self.http_status,self.throttle_seconds,self.url,self.body,self.headers,self.message,self.error_status,self.message_data)
Method generated by attrs for class ResponseError.
Inherited Members
- HTTPException
- error_code
- http_status
- throttle_seconds
- url
- body
- headers
- message
- error_status
- message_data
- builtins.BaseException
- with_traceback
- args
517@typing.final 518class Stat(int, Enum): 519 """An Enum for Destiny 2 character stats.""" 520 521 NONE = 0 522 MOBILITY = 2996146975 523 RESILIENCE = 392767087 524 RECOVERY = 1943323491 525 DISCIPLINE = 1735777505 526 INTELLECT = 144602215 527 STRENGTH = 4244567218 528 LIGHT_POWER = 1935470627
An Enum for Destiny 2 character stats.
632@typing.final 633class TierType(int, Enum): 634 """An enum for a Destiny 2 item tier type.""" 635 636 UNKNOWN = 0 637 CURRENCY = 1 638 BASIC = 2 639 COMMON = 3 640 RARE = 4 641 SUPERIOR = 5 642 EXOTIC = 6
An enum for a Destiny 2 item tier type.
742@typing.final 743class TransferStatus(Flag): 744 """An enum for items transfer statuses.""" 745 746 CAN_TRANSFER = 0 747 """The item can be transferred.""" 748 IS_EQUIPPED = 1 << 0 749 """You can't transfer since the item is equipped.""" 750 NOT_TRASNFERRABLE = 1 << 1 751 """This item can not be transferred.""" 752 COULD_BE_TRANSFERRED = 1 << 2 753 """You can transfer the item. But the place you're trying to put it at has no space for it."""
An enum for items transfer statuses.
You can transfer the item. But the place you're trying to put it at has no space for it.
33class UndefinedType: 34 """An `UNDEFINED` type.""" 35 36 __instance: typing.Optional[UndefinedType] = None 37 38 def __bool__(self) -> typing.Literal[False]: 39 return False 40 41 def __int__(self) -> typing.Literal[0]: 42 return 0 43 44 def __repr__(self) -> str: 45 return "UNDEFINED" 46 47 def __str__(self) -> str: 48 return "UNDEFINED" 49 50 def __new__(cls) -> UndefinedType: 51 if cls.__instance is None: 52 o = super().__new__(cls) 53 cls.__instance = o 54 return cls.__instance
An UNDEFINED type.
75@typing.final 76class ValueUIStyle(int, enums.Enum): 77 AUTOMATIC = 0 78 FRACTION = 1 79 CHECK_BOX = 2 80 PERCENTAGE = 3 81 DATETIME = 4 82 FRACTION_FLOAT = 5 83 INTEGER = 6 84 TIME_DURATION = 7 85 HIDDEN = 8 86 MULTIPLIER = 9 87 GREEN_PIPS = 10 88 RED_PIPS = 11 89 EXPLICIT_PERCENTAGE = 12 90 RAW_FLOAT = 13 91 LEVEL_AND_REWARD = 14
An enumeration.
240@typing.final 241class Vendor(int, Enum): 242 """An Enum for all available vendors in Destiny 2.""" 243 244 ZAVALA = 69482069 245 XUR = 2190858386 246 BANSHE = 672118013 247 SPIDER = 863940356 248 SHAXX = 3603221665 249 KADI = 529635856 250 """Postmaster exo.""" 251 YUNA = 1796504621 252 """Asia servers only.""" 253 EVERVERSE = 3361454721 254 AMANDA = 460529231 255 """Amanda holiday""" 256 CROW = 3611983588 257 HAWTHORNE = 3347378076 258 ADA1 = 350061650 259 DRIFTER = 248695599 260 IKORA = 1976548992 261 SAINT = 765357505 262 """Saint-14""" 263 ERIS_MORN = 1616085565 264 SHAW_HAWN = 1816541247 265 """COSMODROME Guy""" 266 VARIKS = 2531198101
An Enum for all available vendors in Destiny 2.
531@typing.final 532class WeaponType(int, Enum): 533 """Enums for The three Destiny Weapon Types""" 534 535 NONE = 0 536 KINETIC = 1498876634 537 ENERGY = 2465295065 538 POWER = 953998645
Enums for The three Destiny Weapon Types
559def into_iter( 560 iterable: collections.Iterable[Item], 561) -> Iterator[Item]: 562 """Transform an iterable into an flat iterator. 563 564 Example 565 ------- 566 ```py 567 sequence = [1,2,3] 568 for item in aiobungie.into_iter(sequence).reversed(): 569 print(item) 570 # 3 571 # 2 572 # 1 573 ``` 574 575 Parameters 576 ---------- 577 iterable: `typing.Iterable[Item]` 578 The iterable to convert. 579 580 Raises 581 ------ 582 `StopIteration` 583 If no elements are left in the iterator. 584 """ 585 return Iterator(iterable)
Transform an iterable into an flat iterator.
Example
sequence = [1,2,3]
for item in aiobungie.into_iter(sequence).reversed():
print(item)
# 3
# 2
# 1
Parameters
- iterable (
typing.Iterable[Item]): The iterable to convert.
Raises
StopIteration: If no elements are left in the iterator.
282async def raise_error(response: aiohttp.ClientResponse) -> AiobungieError: 283 """Generates and raise exceptions on error responses.""" 284 285 # Not a JSON response, raise immediately. 286 287 # Also Bungie sometimes get funky and return HTML instead of JSON when making an authorized 288 # request with a dummy access token. I can't really do anything about this.. 289 if response.content_type != "application/json": 290 return HTTPError( 291 f"Expected JSON content but got {response.content_type!s}, {response.real_url!s}", 292 http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE, 293 ) 294 295 body = await response.json() 296 message: str = body.get("Message", "UNDEFINED_MESSAGE") 297 error_status: str = body.get("ErrorStatus", "UNDEFINED_ERROR_STATUS") 298 message_data: dict[str, str] = body.get("MessageData", {}) 299 throttle_seconds: int = body.get("ThrottleSeconds", 0) 300 error_code: int = body.get("ErrorCode", 0) 301 302 # Standard HTTP status. 303 if response.status == http.HTTPStatus.NOT_FOUND: 304 return NotFound( 305 message=message, 306 error_code=error_code, 307 throttle_seconds=throttle_seconds, 308 url=str(response.real_url), 309 body=body, 310 headers=response.headers, 311 error_status=error_status, 312 message_data=message_data, 313 ) 314 315 elif response.status == http.HTTPStatus.FORBIDDEN: 316 return Forbidden( 317 message=message, 318 error_code=error_code, 319 throttle_seconds=throttle_seconds, 320 url=str(response.real_url), 321 body=body, 322 headers=response.headers, 323 error_status=error_status, 324 message_data=message_data, 325 ) 326 327 elif response.status == http.HTTPStatus.UNAUTHORIZED: 328 return Unauthorized( 329 message=message, 330 error_code=error_code, 331 throttle_seconds=throttle_seconds, 332 url=str(response.real_url), 333 body=body, 334 headers=response.headers, 335 error_status=error_status, 336 message_data=message_data, 337 ) 338 339 elif response.status == http.HTTPStatus.BAD_REQUEST: 340 # Membership needs to be alone. 341 if error_status == "InvalidParameters": 342 return MembershipTypeError( 343 message=message, 344 body=body, 345 headers=response.headers, 346 url=str(response.url), 347 membership_type=message_data["membershipType"], 348 required_membership=message_data["membershipInfo.membershipType"], 349 membership_id=int(message_data["membershipId"]), 350 ) 351 return BadRequest( 352 message=message, 353 body=body, 354 headers=response.headers, 355 url=str(response.url), 356 ) 357 358 status = http.HTTPStatus(response.status) 359 360 if 400 <= status < 500: 361 return ResponseError( 362 message=message, 363 error_code=error_code, 364 throttle_seconds=throttle_seconds, 365 url=str(response.real_url), 366 body=body, 367 headers=response.headers, 368 error_status=error_status, 369 message_data=message_data, 370 http_status=status, 371 ) 372 373 # Need to self handle ~5xx errors 374 elif 500 <= status < 600: 375 # No API key or method requires OAuth2 most likely. 376 if error_status in { 377 "ApiKeyMissingFromRequest", 378 "WebAuthRequired", 379 "ApiInvalidOrExpiredKey", 380 "AuthenticationInvalid", 381 "AuthorizationCodeInvalid", 382 }: 383 return Unauthorized( 384 message=message, 385 error_code=error_code, 386 throttle_seconds=throttle_seconds, 387 url=str(response.real_url), 388 body=body, 389 headers=response.headers, 390 error_status=error_status, 391 message_data=message_data, 392 ) 393 394 # Anything contains not found. 395 elif ( 396 "NotFound" in error_status or error_status == "UserCannotFindRequestedUser" 397 ): 398 return NotFound( 399 message=message, 400 error_code=error_code, 401 throttle_seconds=throttle_seconds, 402 url=str(response.real_url), 403 body=body, 404 headers=response.headers, 405 error_status=error_status, 406 message_data=message_data, 407 ) 408 409 # Other 5xx errors. 410 else: 411 return InternalServerError( 412 message=message, 413 error_code=error_code, 414 throttle_seconds=throttle_seconds, 415 url=str(response.real_url), 416 body=body, 417 headers=response.headers, 418 error_status=error_status, 419 message_data=message_data, 420 http_status=status, 421 ) 422 # Something else. 423 else: 424 return HTTPException( 425 message=message, 426 error_code=error_code, 427 throttle_seconds=throttle_seconds, 428 url=str(response.real_url), 429 body=body, 430 headers=response.headers, 431 error_status=error_status, 432 message_data=message_data, 433 http_status=status, 434 )
Generates and raise exceptions on error responses.
437def stringify_http_message(headers: collections.Mapping[str, str]) -> str: 438 return ( 439 "{ \n" 440 + "\n".join( # noqa: W503 441 f"{f' {key}'}: {value}" 442 if key not in ("Authorization", "X-API-KEY") 443 else f" {key}: HIDDEN_TOKEN" 444 for key, value in headers.items() 445 ) 446 + "\n}" # noqa: W503 447 )